Compare commits
305 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
cc2110449c | ||
|
|
f6ca49e05f | ||
|
|
9a7331b2e2 | ||
|
|
4888afd423 | ||
|
|
0dc523b081 | ||
|
|
63772e335d | ||
|
|
7f4ff1e38f | ||
|
|
32ebc1d227 | ||
|
|
4ded155dc0 | ||
|
|
201e1250de | ||
|
|
102b049a32 | ||
|
|
74f49eda64 | ||
|
|
9da3e2cca1 | ||
|
|
e290050821 | ||
|
|
bc9ed0a4ef | ||
|
|
20b9b44973 | ||
|
|
6e5a553235 | ||
|
|
2a08a63f17 | ||
|
|
d4290e6721 | ||
|
|
51bda28a7d | ||
|
|
cc26051b7a | ||
|
|
3ac5a9aa31 | ||
|
|
451047c30d | ||
|
|
6907df489b | ||
|
|
970f882b03 | ||
|
|
3eff9a2860 | ||
|
|
a4a24a0ef3 | ||
|
|
48e3c046b0 | ||
|
|
03e4f5be8a | ||
|
|
99657b7d92 | ||
|
|
40377aa1fc | ||
|
|
2a37017e8c | ||
|
|
ff66d08cef | ||
|
|
dad8035eef | ||
|
|
bf5fec342c | ||
|
|
66a6c81ebf | ||
|
|
5c70f5044b | ||
|
|
953d141ab2 | ||
|
|
07dba46039 | ||
|
|
3b02da9d7b | ||
|
|
20234c6156 | ||
|
|
de767cc026 | ||
|
|
ce1663d302 | ||
|
|
f40e4bcd14 | ||
|
|
e7d40d435f | ||
|
|
ef8fe31c0c | ||
|
|
226f682c99 | ||
|
|
468ffd29fb | ||
|
|
a61126ab23 | ||
|
|
54c7c25861 | ||
|
|
eff7700d92 | ||
|
|
8934f6938d | ||
|
|
8f0fc3033a | ||
|
|
4107bc828d | ||
|
|
706d28cabc | ||
|
|
4da2264722 | ||
|
|
bf88c815aa | ||
|
|
8a4831dd5b | ||
|
|
b5ab492a70 | ||
|
|
1fc09ebd5c | ||
|
|
6cf047976c | ||
|
|
87465daacc | ||
|
|
a52bed7101 | ||
|
|
20ac823778 | ||
|
|
1028ed3565 | ||
|
|
98897db6ac | ||
|
|
5ce4262112 | ||
|
|
6b2359384d | ||
|
|
d3443d7c19 | ||
|
|
04b1e1de6f | ||
|
|
c93c85300f | ||
|
|
73ed6f8654 | ||
|
|
eb183645f3 | ||
|
|
ef17aa93da | ||
|
|
f366b0147f | ||
|
|
fc88fa35ff | ||
|
|
a2806eb8ef | ||
|
|
89d919eac5 | ||
|
|
5ad77fbc8d | ||
|
|
9cb18a481b | ||
|
|
2393e270ed | ||
|
|
f36e6035c8 | ||
|
|
ecf0dd05d6 | ||
|
|
5f67ee93f7 | ||
|
|
1e19142d0e | ||
|
|
6a95dade6d | ||
|
|
d6e765877e | ||
|
|
e4d36bae57 | ||
|
|
e3531276a7 | ||
|
|
634553f188 | ||
|
|
4ff0b75045 | ||
|
|
481d668511 | ||
|
|
a9f56ee76e | ||
|
|
b4bfa87104 | ||
|
|
b9f42bf5e5 | ||
|
|
8281d414ca | ||
|
|
7e45a9f2e2 | ||
|
|
a000cd4a09 | ||
|
|
d8b4b92733 | ||
|
|
27de342e75 | ||
|
|
d805067683 | ||
|
|
1ea2e93f8e | ||
|
|
dc180dc277 | ||
|
|
6be910ae07 | ||
|
|
ba85eb846c | ||
|
|
d067efe265 | ||
|
|
549ea2f85f | ||
|
|
d814ebd21f | ||
|
|
3f272b6cf8 | ||
|
|
76891a8c07 | ||
|
|
e389201b5f | ||
|
|
4b2020d03a | ||
|
|
0aa356c96c | ||
|
|
630b4b627d | ||
|
|
854cd14842 | ||
|
|
6b93c8403f | ||
|
|
765d21c7b0 | ||
|
|
a58b9b5063 | ||
|
|
f3e11a30cb | ||
|
|
2f3b5367ff | ||
|
|
92bc417e4e | ||
|
|
9853b0728b | ||
|
|
77709dcc41 | ||
|
|
b0cb5fc7ef | ||
|
|
d6f51e55dd | ||
|
|
4bb6b4851a | ||
|
|
54c5ded938 | ||
|
|
0157fedab5 | ||
|
|
cd69610741 | ||
|
|
a3d06d0005 | ||
|
|
ac6fa1dc88 | ||
|
|
73794fc299 | ||
|
|
0adc9ed259 | ||
|
|
19e9eb1af8 | ||
|
|
e57044800c | ||
|
|
ae8ff7cb7f | ||
|
|
c05914f222 | ||
|
|
24179655b8 | ||
|
|
d27b419e68 | ||
|
|
9fc7a32a24 | ||
|
|
9161b866b5 | ||
|
|
38141a6f14 | ||
|
|
aa5402fc0e | ||
|
|
99f077aa4e | ||
|
|
7f25d1ec70 | ||
|
|
360b033e04 | ||
|
|
247dcc9f9c | ||
|
|
c86e52193c | ||
|
|
efdc4e801d | ||
|
|
f8f2eeed35 | ||
|
|
8fa414b67e | ||
|
|
484d7a30bd | ||
|
|
fb681c614a | ||
|
|
06ed125771 | ||
|
|
74668915b0 | ||
|
|
6da3de25ba | ||
|
|
63b3e00c97 | ||
|
|
39440aa274 | ||
|
|
add96d3dc5 | ||
|
|
6f8e0224d0 | ||
|
|
b8bbafd85b | ||
|
|
40b54d3e8c | ||
|
|
2b44941d63 | ||
|
|
257bd7f1d7 | ||
|
|
5728dceef0 | ||
|
|
6739602806 | ||
|
|
305326f7d7 | ||
|
|
69866f5461 | ||
|
|
41ca29c4f4 | ||
|
|
b35a804f9d | ||
|
|
e594ed6528 | ||
|
|
197645d90d | ||
|
|
26d3ff5a3a | ||
|
|
0dacf61153 | ||
|
|
a6251360b7 | ||
|
|
2965e2561d | ||
|
|
a19050b8a4 | ||
|
|
dfd6225d85 | ||
|
|
a0a6327fae | ||
|
|
db815a565f | ||
|
|
3bacdafd1c | ||
|
|
6403e3630d | ||
|
|
229eab6f42 | ||
|
|
e33582fb0e | ||
|
|
aaeab0ecf1 | ||
|
|
f9a16d9c44 | ||
|
|
2aa884eb9b | ||
|
|
84fa64d98c | ||
|
|
c1b1ac069e | ||
|
|
a710e35ebc | ||
|
|
49df43bb78 | ||
|
|
e338d9acbe | ||
|
|
5c8655f479 | ||
|
|
60987888a2 | ||
|
|
a81581c781 | ||
|
|
3152dd7a8e | ||
|
|
528416f07a | ||
|
|
4405a6a903 | ||
|
|
35fa2a3c32 | ||
|
|
bb67fbb73a | ||
|
|
d698c6123e | ||
|
|
9579faffa8 | ||
|
|
9c6e8c7644 | ||
|
|
7abecd4f0e | ||
|
|
b8ff209af8 | ||
|
|
c5451cd8ad | ||
|
|
92b9ab3010 | ||
|
|
f2ac8c4ec2 | ||
|
|
80e2f0c92e | ||
|
|
ea550abd3c | ||
|
|
5c26777e4c | ||
|
|
6eb6b6eede | ||
|
|
f1d3e3698a | ||
|
|
080411bc89 | ||
|
|
f2ad915224 | ||
|
|
71543eeabc | ||
|
|
44025f1c92 | ||
|
|
971bf6d232 | ||
|
|
0acc47386a | ||
|
|
982ac6b0ad | ||
|
|
541440f7a8 | ||
|
|
66dde46e03 | ||
|
|
1339e2a002 | ||
|
|
38ad10f60d | ||
|
|
88e78c5cde | ||
|
|
436aeed20a | ||
|
|
b94169a8bb | ||
|
|
995994be3e | ||
|
|
f001305b2e | ||
|
|
e88093541f | ||
|
|
da41a495f1 | ||
|
|
55b7ec8f85 | ||
|
|
4b41ae3f53 | ||
|
|
f944e1e1cf | ||
|
|
4fbc1082de | ||
|
|
cf2e887e38 | ||
|
|
ee994e8c07 | ||
|
|
c69c4fd655 | ||
|
|
e01e45ca35 | ||
|
|
4be74785fe | ||
|
|
40b7c64f7d | ||
|
|
a76c5d1226 | ||
|
|
5aeddeb825 | ||
|
|
5f8294aea4 | ||
|
|
e07d3f6313 | ||
|
|
1d1662cb9c | ||
|
|
55ce7bd0df | ||
|
|
e695f6eb25 | ||
|
|
fb2c457a9b | ||
|
|
523cf62eda | ||
|
|
7024ad7cc7 | ||
|
|
871ac511ae | ||
|
|
0685af8a4f | ||
|
|
5e9a8fcf53 | ||
|
|
76439235af | ||
|
|
0c9c6a1c1c | ||
|
|
46a99243cd | ||
|
|
d06dc4c72d | ||
|
|
8f6b2fb32b | ||
|
|
1d61db5b62 | ||
|
|
e15c0c68cb | ||
|
|
abb2adc4d8 | ||
|
|
e070166409 | ||
|
|
0ae6890094 | ||
|
|
21cace0973 | ||
|
|
4994b72ba2 | ||
|
|
dbb1a6e44b |
49
.github/workflows/ci.yaml
vendored
49
.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:
|
||||
@@ -20,6 +20,9 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
components: rustfmt
|
||||
- uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-cargo
|
||||
@@ -33,8 +36,14 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: cargo build --all --release
|
||||
- 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:
|
||||
@@ -70,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
|
||||
@@ -83,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:
|
||||
@@ -106,9 +117,37 @@ jobs:
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: pip install black[d]==22.12.0
|
||||
- run: cargo test --all
|
||||
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
|
||||
|
||||
maturin_build:
|
||||
wasm-pack-test:
|
||||
name: "wasm-pack test"
|
||||
runs-on: ubuntu-latest
|
||||
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:
|
||||
@@ -120,7 +159,7 @@ jobs:
|
||||
override: true
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: "3.11"
|
||||
- run: pip install maturin
|
||||
- uses: actions/cache@v3
|
||||
env:
|
||||
|
||||
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}
|
||||
5
.github/workflows/ruff.yaml
vendored
5
.github/workflows/ruff.yaml
vendored
@@ -1,9 +1,8 @@
|
||||
name: "[ruff] Release"
|
||||
|
||||
on:
|
||||
create:
|
||||
tags:
|
||||
- v*
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.155
|
||||
rev: v0.0.196
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
23
BREAKING_CHANGES.md
Normal file
23
BREAKING_CHANGES.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Breaking Changes
|
||||
|
||||
## 0.0.181
|
||||
|
||||
### Files excluded by `.gitignore` are now ignored ([#1234](https://github.com/charliermarsh/ruff/pull/1234))
|
||||
|
||||
Ruff will now avoid checking files that are excluded by `.ignore`, `.gitignore`,
|
||||
`.git/info/exclude`, and global `gitignore` files. This behavior is powered by the [`ignore`](https://docs.rs/ignore/latest/ignore/struct.WalkBuilder.html#ignore-rules)
|
||||
crate, and is applied in addition to Ruff's built-in `exclude` system.
|
||||
|
||||
To disable this behavior, set `respect-gitignore = false` in your `pyproject.toml` file.
|
||||
|
||||
Note that hidden files (i.e., files and directories prefixed with a `.`) are _not_ ignored by
|
||||
default.
|
||||
|
||||
## 0.0.178
|
||||
|
||||
### Configuration files are now resolved hierarchically ([#1190](https://github.com/charliermarsh/ruff/pull/1190))
|
||||
|
||||
`pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find
|
||||
the first `pyproject.toml` file in its path, and use that to determine its lint settings.
|
||||
|
||||
See the [README](https://github.com/charliermarsh/ruff#pyprojecttoml-discovery) for more.
|
||||
@@ -48,8 +48,8 @@ prior to merging.
|
||||
There are four phases to adding a new lint rule:
|
||||
|
||||
1. Define the rule in `src/checks.rs`.
|
||||
2. Define the _logic_ for triggering the rule in `src/check_ast.rs` (for AST-based checks),
|
||||
`src/check_tokens.rs` (for token-based checks), or `src/check_lines.rs` (for text-based checks).
|
||||
2. Define the _logic_ for triggering the rule in `src/checkers/ast.rs` (for AST-based checks),
|
||||
`src/checkers/tokens.rs` (for token-based checks), or `src/checkers/lines.rs` (for text-based checks).
|
||||
3. Add a test fixture.
|
||||
4. Update the generated files (documentation and generated code).
|
||||
|
||||
@@ -59,9 +59,9 @@ 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
|
||||
@@ -79,9 +79,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,6 +103,8 @@ 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`.
|
||||
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
## Release process
|
||||
|
||||
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub
|
||||
|
||||
672
Cargo.lock
generated
672
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
45
Cargo.toml
45
Cargo.toml
@@ -6,12 +6,13 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.155"
|
||||
version = "0.0.196"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
@@ -20,54 +21,71 @@ 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" }
|
||||
fern = { version = "0.6.1" }
|
||||
filetime = { version = "0.2.17" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
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 = "4.0.17" }
|
||||
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.196", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "f885db8c61514f069979861f6b3bd83292086231" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "f885db8c61514f069979861f6b3bd83292086231" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "f885db8c61514f069979861f6b3bd83292086231" }
|
||||
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" }
|
||||
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"]
|
||||
@@ -85,6 +103,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
|
||||
|
||||
75
LICENSE
75
LICENSE
@@ -388,6 +388,81 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-import-conventions, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 João Palmeiro
|
||||
|
||||
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-unused-arguments, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Nathan Hoad
|
||||
|
||||
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-simplify, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Martin Thoma
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- isort, licensed as follows:
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
set -euxo pipefail
|
||||
|
||||
NAME=$1
|
||||
|
||||
mkdir -p src/$1
|
||||
mkdir -p resources/test/fixtures/$1
|
||||
touch src/$1/mod.rs
|
||||
|
||||
sed -i "" "s/mod flake8_print;/mod flake8_print; mod flake8_return;/g" src/lib.rs
|
||||
sed -i "" "s|// flake8-print|// flake8-return\n// flake8-print|g" src/checks.rs
|
||||
|
||||
12
flake8_to_ruff/Cargo.lock
generated
12
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.155"
|
||||
version = "0.0.196"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.155"
|
||||
version = "0.0.196"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@@ -2028,7 +2028,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -2038,7 +2038,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -2061,7 +2061,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2078,7 +2078,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.155-dev.0"
|
||||
version = "0.0.196-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
@@ -16,6 +16,8 @@ ruff = { path = "..", default-features = false }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
toml = { version = "0.5.9" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
65
flake8_to_ruff/examples/cryptography/pyproject.toml
Normal file
65
flake8_to_ruff/examples/cryptography/pyproject.toml
Normal file
@@ -0,0 +1,65 @@
|
||||
[build-system]
|
||||
requires = [
|
||||
# The minimum setuptools version is specific to the PEP 517 backend,
|
||||
# and may be stricter than the version required in `setup.cfg`
|
||||
"setuptools>=40.6.0,!=60.9.0",
|
||||
"wheel",
|
||||
# Must be kept in sync with the `install_requirements` in `setup.cfg`
|
||||
"cffi>=1.12; platform_python_implementation != 'PyPy'",
|
||||
"setuptools-rust>=0.11.4",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.black]
|
||||
line-length = 79
|
||||
target-version = ["py36"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "-r s --capture=no --strict-markers --benchmark-disable"
|
||||
markers = [
|
||||
"skip_fips: this test is not executed in FIPS mode",
|
||||
"supported: parametrized test requiring only_if and skip_message",
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
show_error_codes = true
|
||||
check_untyped_defs = true
|
||||
no_implicit_reexport = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
warn_unused_configs = true
|
||||
strict_equality = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"pretend"
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
relative_files = true
|
||||
source = [
|
||||
"cryptography",
|
||||
"tests/",
|
||||
]
|
||||
|
||||
[tool.coverage.paths]
|
||||
source = [
|
||||
"src/cryptography",
|
||||
"*.tox/*/lib*/python*/site-packages/cryptography",
|
||||
"*.tox\\*\\Lib\\site-packages\\cryptography",
|
||||
"*.tox/pypy/site-packages/cryptography",
|
||||
]
|
||||
tests =[
|
||||
"tests/",
|
||||
"*tests\\",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"@abc.abstractmethod",
|
||||
"@abc.abstractproperty",
|
||||
"@typing.overload",
|
||||
"if typing.TYPE_CHECKING",
|
||||
]
|
||||
91
flake8_to_ruff/examples/cryptography/setup.cfg
Normal file
91
flake8_to_ruff/examples/cryptography/setup.cfg
Normal file
@@ -0,0 +1,91 @@
|
||||
[metadata]
|
||||
name = cryptography
|
||||
version = attr: cryptography.__version__
|
||||
description = cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
||||
long_description = file: README.rst
|
||||
long_description_content_type = text/x-rst
|
||||
license = BSD-3-Clause OR Apache-2.0
|
||||
url = https://github.com/pyca/cryptography
|
||||
author = The Python Cryptographic Authority and individual contributors
|
||||
author_email = cryptography-dev@python.org
|
||||
project_urls =
|
||||
Documentation=https://cryptography.io/
|
||||
Source=https://github.com/pyca/cryptography/
|
||||
Issues=https://github.com/pyca/cryptography/issues
|
||||
Changelog=https://cryptography.io/en/latest/changelog/
|
||||
classifiers =
|
||||
Development Status :: 5 - Production/Stable
|
||||
Intended Audience :: Developers
|
||||
License :: OSI Approved :: Apache Software License
|
||||
License :: OSI Approved :: BSD License
|
||||
Natural Language :: English
|
||||
Operating System :: MacOS :: MacOS X
|
||||
Operating System :: POSIX
|
||||
Operating System :: POSIX :: BSD
|
||||
Operating System :: POSIX :: Linux
|
||||
Operating System :: Microsoft :: Windows
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
Programming Language :: Python :: 3.11
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
Programming Language :: Python :: Implementation :: PyPy
|
||||
Topic :: Security :: Cryptography
|
||||
|
||||
[options]
|
||||
python_requires = >=3.6
|
||||
include_package_data = True
|
||||
zip_safe = False
|
||||
package_dir =
|
||||
=src
|
||||
packages = find:
|
||||
# `install_requires` must be kept in sync with `pyproject.toml`
|
||||
install_requires =
|
||||
cffi >=1.12
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
exclude =
|
||||
_cffi_src
|
||||
_cffi_src.*
|
||||
|
||||
[options.extras_require]
|
||||
test =
|
||||
pytest>=6.2.0
|
||||
pytest-benchmark
|
||||
pytest-cov
|
||||
pytest-subtests
|
||||
pytest-xdist
|
||||
pretend
|
||||
iso8601
|
||||
pytz
|
||||
hypothesis>=1.11.4,!=3.79.2
|
||||
docs =
|
||||
sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0
|
||||
sphinx_rtd_theme
|
||||
docstest =
|
||||
pyenchant >= 1.6.11
|
||||
twine >= 1.12.0
|
||||
sphinxcontrib-spelling >= 4.0.1
|
||||
sdist =
|
||||
setuptools_rust >= 0.11.4
|
||||
pep8test =
|
||||
black
|
||||
flake8
|
||||
flake8-import-order
|
||||
pep8-naming
|
||||
# This extra is for OpenSSH private keys that use bcrypt KDF
|
||||
# Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3
|
||||
ssh =
|
||||
bcrypt >= 3.1.5
|
||||
|
||||
[flake8]
|
||||
ignore = E203,E211,W503,W504,N818
|
||||
exclude = .tox,*.egg,.git,_build,.hypothesis
|
||||
select = E,W,F,N,I
|
||||
application-import-names = cryptography,cryptography_vectors,tests
|
||||
@@ -12,6 +12,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
|
||||
32
flake8_to_ruff/src/black.rs
Normal file
32
flake8_to_ruff/src/black.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
//! Extract Black configuration settings from a pyproject.toml.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use ruff::settings::types::PythonVersion;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
pub struct Black {
|
||||
#[serde(alias = "line-length", alias = "line_length")]
|
||||
pub line_length: Option<usize>,
|
||||
#[serde(alias = "target-version", alias = "target_version")]
|
||||
pub target_version: Option<Vec<PythonVersion>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
struct Tools {
|
||||
black: Option<Black>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
struct Pyproject {
|
||||
tool: Option<Tools>,
|
||||
}
|
||||
|
||||
pub fn parse_black_options<P: AsRef<Path>>(path: P) -> Result<Option<Black>> {
|
||||
let contents = std::fs::read_to_string(path)?;
|
||||
Ok(toml::from_str::<Pyproject>(&contents)?
|
||||
.tool
|
||||
.and_then(|tool| tool.black))
|
||||
}
|
||||
@@ -7,16 +7,24 @@ use ruff::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{
|
||||
flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, mccabe, pep8_naming,
|
||||
flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_quotes, flake8_tidy_imports, mccabe,
|
||||
pep8_naming,
|
||||
};
|
||||
|
||||
use crate::black::Black;
|
||||
use crate::plugin::Plugin;
|
||||
use crate::{parser, plugin};
|
||||
|
||||
pub fn convert(
|
||||
flake8: &HashMap<String, Option<String>>,
|
||||
config: &HashMap<String, HashMap<String, Option<String>>>,
|
||||
black: Option<&Black>,
|
||||
plugins: Option<Vec<Plugin>>,
|
||||
) -> Result<Pyproject> {
|
||||
// Extract the Flake8 section.
|
||||
let flake8 = config
|
||||
.get("flake8")
|
||||
.expect("Unable to find flake8 section in INI file");
|
||||
|
||||
// Extract all referenced check code prefixes, to power plugin inference.
|
||||
let mut referenced_codes: BTreeSet<CheckCodePrefix> = BTreeSet::default();
|
||||
for (key, value) in flake8 {
|
||||
@@ -53,10 +61,15 @@ pub fn convert(
|
||||
plugin::resolve_select(
|
||||
flake8,
|
||||
&plugins.unwrap_or_else(|| {
|
||||
plugin::infer_plugins_from_options(flake8)
|
||||
.into_iter()
|
||||
.chain(plugin::infer_plugins_from_codes(&referenced_codes))
|
||||
.collect()
|
||||
let from_options = plugin::infer_plugins_from_options(flake8);
|
||||
if !from_options.is_empty() {
|
||||
eprintln!("Inferred plugins from settings: {from_options:#?}");
|
||||
}
|
||||
let from_codes = plugin::infer_plugins_from_codes(&referenced_codes);
|
||||
if !from_codes.is_empty() {
|
||||
eprintln!("Inferred plugins from referenced check codes: {from_codes:#?}");
|
||||
}
|
||||
from_options.into_iter().chain(from_codes).collect()
|
||||
}),
|
||||
)
|
||||
});
|
||||
@@ -73,6 +86,7 @@ pub fn convert(
|
||||
let mut options = Options::default();
|
||||
let mut flake8_annotations = flake8_annotations::settings::Options::default();
|
||||
let mut flake8_bugbear = flake8_bugbear::settings::Options::default();
|
||||
let mut flake8_errmsg = flake8_errmsg::settings::Options::default();
|
||||
let mut flake8_quotes = flake8_quotes::settings::Options::default();
|
||||
let mut flake8_tidy_imports = flake8_tidy_imports::settings::Options::default();
|
||||
let mut mccabe = mccabe::settings::Options::default();
|
||||
@@ -194,6 +208,15 @@ pub fn convert(
|
||||
Ok(max_complexity) => mccabe.max_complexity = Some(max_complexity),
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
},
|
||||
// flake8-errmsg
|
||||
"errmsg-max-string-length" | "errmsg_max_string_length" => {
|
||||
match value.clone().parse::<usize>() {
|
||||
Ok(max_string_length) => {
|
||||
flake8_errmsg.max_string_length = Some(max_string_length);
|
||||
}
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
// Unknown
|
||||
_ => eprintln!("Skipping unsupported property: {key}"),
|
||||
}
|
||||
@@ -209,6 +232,9 @@ pub fn convert(
|
||||
if flake8_bugbear != flake8_bugbear::settings::Options::default() {
|
||||
options.flake8_bugbear = Some(flake8_bugbear);
|
||||
}
|
||||
if flake8_errmsg != flake8_errmsg::settings::Options::default() {
|
||||
options.flake8_errmsg = Some(flake8_errmsg);
|
||||
}
|
||||
if flake8_quotes != flake8_quotes::settings::Options::default() {
|
||||
options.flake8_quotes = Some(flake8_quotes);
|
||||
}
|
||||
@@ -222,6 +248,19 @@ pub fn convert(
|
||||
options.pep8_naming = Some(pep8_naming);
|
||||
}
|
||||
|
||||
// Extract any settings from the existing `pyproject.toml`.
|
||||
if let Some(black) = black {
|
||||
if let Some(line_length) = &black.line_length {
|
||||
options.line_length = Some(*line_length);
|
||||
}
|
||||
|
||||
if let Some(target_version) = &black.target_version {
|
||||
if let Some(target_version) = target_version.iter().min() {
|
||||
options.target_version = Some(*target_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the pyproject.toml.
|
||||
Ok(Pyproject::new(options))
|
||||
}
|
||||
@@ -241,20 +280,31 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn it_converts_empty() -> Result<()> {
|
||||
let actual = convert(&HashMap::from([]), None)?;
|
||||
let actual = convert(
|
||||
&HashMap::from([("flake8".to_string(), HashMap::default())]),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -264,13 +314,18 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -281,22 +336,33 @@ mod tests {
|
||||
#[test]
|
||||
fn it_converts_dashes() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([("max-line-length".to_string(), Some("100".to_string()))]),
|
||||
&HashMap::from([(
|
||||
"flake8".to_string(),
|
||||
HashMap::from([("max-line-length".to_string(), Some("100".to_string()))]),
|
||||
)]),
|
||||
None,
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -306,13 +372,18 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -323,22 +394,33 @@ mod tests {
|
||||
#[test]
|
||||
fn it_converts_underscores() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([("max_line_length".to_string(), Some("100".to_string()))]),
|
||||
&HashMap::from([(
|
||||
"flake8".to_string(),
|
||||
HashMap::from([("max_line_length".to_string(), Some("100".to_string()))]),
|
||||
)]),
|
||||
None,
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -348,13 +430,18 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -365,22 +452,33 @@ mod tests {
|
||||
#[test]
|
||||
fn it_ignores_parse_errors() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([("max_line_length".to_string(), Some("abc".to_string()))]),
|
||||
&HashMap::from([(
|
||||
"flake8".to_string(),
|
||||
HashMap::from([("max_line_length".to_string(), Some("abc".to_string()))]),
|
||||
)]),
|
||||
None,
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -390,13 +488,18 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -407,22 +510,33 @@ mod tests {
|
||||
#[test]
|
||||
fn it_converts_plugin_options() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
|
||||
&HashMap::from([(
|
||||
"flake8".to_string(),
|
||||
HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
|
||||
)]),
|
||||
None,
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -432,8 +546,10 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
@@ -441,9 +557,12 @@ mod tests {
|
||||
avoid_escape: None,
|
||||
}),
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -455,24 +574,35 @@ mod tests {
|
||||
fn it_converts_docstring_conventions() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([(
|
||||
"docstring-convention".to_string(),
|
||||
Some("numpy".to_string()),
|
||||
"flake8".to_string(),
|
||||
HashMap::from([(
|
||||
"docstring-convention".to_string(),
|
||||
Some("numpy".to_string()),
|
||||
)]),
|
||||
)]),
|
||||
None,
|
||||
Some(vec![Plugin::Flake8Docstrings]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
@@ -495,6 +625,7 @@ mod tests {
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D403,
|
||||
CheckCodePrefix::D404,
|
||||
@@ -517,13 +648,18 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -534,22 +670,33 @@ mod tests {
|
||||
#[test]
|
||||
fn it_infers_plugins_if_omitted() -> Result<()> {
|
||||
let actual = convert(
|
||||
&HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
|
||||
&HashMap::from([(
|
||||
"flake8".to_string(),
|
||||
HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
|
||||
)]),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
ignore: Some(vec![]),
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
@@ -560,8 +707,10 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
@@ -569,9 +718,12 @@ mod tests {
|
||||
avoid_escape: None,
|
||||
}),
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
flake8_unused_arguments: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
pub mod black;
|
||||
pub mod converter;
|
||||
mod parser;
|
||||
pub mod plugin;
|
||||
|
||||
@@ -17,6 +17,7 @@ use std::path::PathBuf;
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use configparser::ini::Ini;
|
||||
use flake8_to_ruff::black::parse_black_options;
|
||||
use flake8_to_ruff::converter;
|
||||
use flake8_to_ruff::plugin::Plugin;
|
||||
|
||||
@@ -26,10 +27,14 @@ use flake8_to_ruff::plugin::Plugin;
|
||||
long_about = None
|
||||
)]
|
||||
struct Cli {
|
||||
/// Path to the Flake8 configuration file (e.g., 'setup.cfg', 'tox.ini', or
|
||||
/// '.flake8').
|
||||
/// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or
|
||||
/// `.flake8`).
|
||||
#[arg(required = true)]
|
||||
file: PathBuf,
|
||||
/// Optional path to a `pyproject.toml` file, used to ensure compatibility
|
||||
/// with Black.
|
||||
#[arg(long)]
|
||||
pyproject: Option<PathBuf>,
|
||||
/// List of plugins to enable.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
plugin: Option<Vec<Plugin>>,
|
||||
@@ -43,13 +48,15 @@ fn main() -> Result<()> {
|
||||
ini.set_multiline(true);
|
||||
let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?;
|
||||
|
||||
// Extract the Flake8 section.
|
||||
let flake8 = config
|
||||
.get("flake8")
|
||||
.expect("Unable to find flake8 section in INI file");
|
||||
// Read the pyproject.toml file.
|
||||
let black = cli
|
||||
.pyproject
|
||||
.map(parse_black_options)
|
||||
.transpose()?
|
||||
.flatten();
|
||||
|
||||
// Create the pyproject.toml.
|
||||
let pyproject = converter::convert(flake8, cli.plugin)?;
|
||||
// Create Ruff's pyproject.toml section.
|
||||
let pyproject = converter::convert(&config, black.as_ref(), cli.plugin)?;
|
||||
println!("{}", toml::to_string_pretty(&pyproject)?);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::str::FromStr;
|
||||
use anyhow::{bail, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use ruff::checks::PREFIX_REDIRECTS;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
use rustc_hash::FxHashMap;
|
||||
@@ -18,7 +19,9 @@ pub fn parse_prefix_codes(value: &str) -> Vec<CheckCodePrefix> {
|
||||
if code.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let Ok(code) = CheckCodePrefix::from_str(code) {
|
||||
if let Some(code) = PREFIX_REDIRECTS.get(code) {
|
||||
codes.push(code.clone());
|
||||
} else if let Ok(code) = CheckCodePrefix::from_str(code) {
|
||||
codes.push(code);
|
||||
} else {
|
||||
eprintln!("Unsupported prefix code: {code}");
|
||||
@@ -83,16 +86,22 @@ impl State {
|
||||
fn parse(&self) -> Vec<PatternPrefixPair> {
|
||||
let mut codes: Vec<PatternPrefixPair> = vec![];
|
||||
for code in &self.codes {
|
||||
match CheckCodePrefix::from_str(code) {
|
||||
Ok(code) => {
|
||||
for filename in &self.filenames {
|
||||
codes.push(PatternPrefixPair {
|
||||
pattern: filename.clone(),
|
||||
prefix: code.clone(),
|
||||
});
|
||||
}
|
||||
if let Some(code) = PREFIX_REDIRECTS.get(code.as_str()) {
|
||||
for filename in &self.filenames {
|
||||
codes.push(PatternPrefixPair {
|
||||
pattern: filename.clone(),
|
||||
prefix: code.clone(),
|
||||
});
|
||||
}
|
||||
Err(_) => eprintln!("Skipping unrecognized prefix: {code}"),
|
||||
} else if let Ok(code) = CheckCodePrefix::from_str(code) {
|
||||
for filename in &self.filenames {
|
||||
codes.push(PatternPrefixPair {
|
||||
pattern: filename.clone(),
|
||||
prefix: code.clone(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
eprintln!("Unsupported prefix code: {code}");
|
||||
}
|
||||
}
|
||||
codes
|
||||
@@ -135,7 +144,6 @@ fn tokenize_files_to_codes_mapping(value: &str) -> Vec<Token> {
|
||||
}
|
||||
|
||||
/// Parse a 'files-to-codes' mapping, mimicking Flake8's internal logic.
|
||||
///
|
||||
/// See: <https://github.com/PyCQA/flake8/blob/7dfe99616fc2f07c0017df2ba5fa884158f3ea8a/src/flake8/utils.py#L45>
|
||||
pub fn parse_files_to_codes_mapping(value: &str) -> Result<Vec<PatternPrefixPair>> {
|
||||
if value.trim().is_empty() {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Plugin {
|
||||
Flake8Annotations,
|
||||
Flake8Bandit,
|
||||
@@ -12,14 +13,18 @@ pub enum Plugin {
|
||||
Flake8Bugbear,
|
||||
Flake8Builtins,
|
||||
Flake8Comprehensions,
|
||||
Flake8Datetimez,
|
||||
Flake8Debugger,
|
||||
Flake8Docstrings,
|
||||
Flake8ErrMsg,
|
||||
Flake8Eradicate,
|
||||
Flake8Print,
|
||||
Flake8Quotes,
|
||||
Flake8Return,
|
||||
Flake8Simplify,
|
||||
Flake8TidyImports,
|
||||
McCabe,
|
||||
PandasVet,
|
||||
PEP8Naming,
|
||||
Pyupgrade,
|
||||
}
|
||||
@@ -35,14 +40,18 @@ impl FromStr for Plugin {
|
||||
"flake8-bugbear" => Ok(Plugin::Flake8Bugbear),
|
||||
"flake8-builtins" => Ok(Plugin::Flake8Builtins),
|
||||
"flake8-comprehensions" => Ok(Plugin::Flake8Comprehensions),
|
||||
"flake8-datetimez" => Ok(Plugin::Flake8Datetimez),
|
||||
"flake8-debugger" => Ok(Plugin::Flake8Debugger),
|
||||
"flake8-docstrings" => Ok(Plugin::Flake8Docstrings),
|
||||
"flake8-eradicate" => Ok(Plugin::Flake8BlindExcept),
|
||||
"flake8-eradicate" => Ok(Plugin::Flake8Eradicate),
|
||||
"flake8-errmsg" => Ok(Plugin::Flake8ErrMsg),
|
||||
"flake8-print" => Ok(Plugin::Flake8Print),
|
||||
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
|
||||
"flake8-return" => Ok(Plugin::Flake8Return),
|
||||
"flake8-simplify" => Ok(Plugin::Flake8Simplify),
|
||||
"flake8-tidy-imports" => Ok(Plugin::Flake8TidyImports),
|
||||
"mccabe" => Ok(Plugin::McCabe),
|
||||
"pandas-vet" => Ok(Plugin::PandasVet),
|
||||
"pep8-naming" => Ok(Plugin::PEP8Naming),
|
||||
"pyupgrade" => Ok(Plugin::Pyupgrade),
|
||||
_ => Err(anyhow!("Unknown plugin: {string}")),
|
||||
@@ -50,25 +59,62 @@ impl FromStr for Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Plugin {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Plugin::Flake8Annotations => "flake8-annotations",
|
||||
Plugin::Flake8Bandit => "flake8-bandit",
|
||||
Plugin::Flake8BlindExcept => "flake8-blind-except",
|
||||
Plugin::Flake8Bugbear => "flake8-bugbear",
|
||||
Plugin::Flake8Builtins => "flake8-builtins",
|
||||
Plugin::Flake8Comprehensions => "flake8-comprehensions",
|
||||
Plugin::Flake8Datetimez => "flake8-datetimez",
|
||||
Plugin::Flake8Debugger => "flake8-debugger",
|
||||
Plugin::Flake8Docstrings => "flake8-docstrings",
|
||||
Plugin::Flake8Eradicate => "flake8-eradicate",
|
||||
Plugin::Flake8ErrMsg => "flake8-errmsg",
|
||||
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::Pyupgrade => "pyupgrade",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Plugin {
|
||||
pub fn default(&self) -> CheckCodePrefix {
|
||||
match self {
|
||||
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
|
||||
Plugin::Flake8Bandit => CheckCodePrefix::S,
|
||||
// TODO(charlie): Handle rename of `B` to `BLE`.
|
||||
Plugin::Flake8BlindExcept => CheckCodePrefix::BLE,
|
||||
Plugin::Flake8Bugbear => CheckCodePrefix::B,
|
||||
Plugin::Flake8Builtins => CheckCodePrefix::A,
|
||||
Plugin::Flake8Comprehensions => CheckCodePrefix::C4,
|
||||
Plugin::Flake8Datetimez => CheckCodePrefix::DTZ,
|
||||
Plugin::Flake8Debugger => CheckCodePrefix::T1,
|
||||
Plugin::Flake8Docstrings => CheckCodePrefix::D,
|
||||
// TODO(charlie): Handle rename of `E` to `ERA`.
|
||||
Plugin::Flake8Eradicate => CheckCodePrefix::ERA,
|
||||
Plugin::Flake8ErrMsg => CheckCodePrefix::EM,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T2,
|
||||
Plugin::Flake8Quotes => CheckCodePrefix::Q,
|
||||
Plugin::Flake8Return => CheckCodePrefix::RET,
|
||||
Plugin::Flake8TidyImports => CheckCodePrefix::I25,
|
||||
Plugin::Flake8Simplify => CheckCodePrefix::SIM,
|
||||
Plugin::Flake8TidyImports => CheckCodePrefix::TID25,
|
||||
Plugin::McCabe => CheckCodePrefix::C9,
|
||||
Plugin::PandasVet => CheckCodePrefix::PD,
|
||||
Plugin::PEP8Naming => CheckCodePrefix::N,
|
||||
Plugin::Pyupgrade => CheckCodePrefix::U,
|
||||
Plugin::Pyupgrade => CheckCodePrefix::UP,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +126,7 @@ impl Plugin {
|
||||
Plugin::Flake8Bugbear => vec![CheckCodePrefix::B],
|
||||
Plugin::Flake8Builtins => vec![CheckCodePrefix::A],
|
||||
Plugin::Flake8Comprehensions => vec![CheckCodePrefix::C4],
|
||||
Plugin::Flake8Datetimez => vec![CheckCodePrefix::DTZ],
|
||||
Plugin::Flake8Debugger => vec![CheckCodePrefix::T1],
|
||||
Plugin::Flake8Docstrings => {
|
||||
// Use the user-provided docstring.
|
||||
@@ -98,13 +145,16 @@ impl Plugin {
|
||||
DocstringConvention::PEP8.select()
|
||||
}
|
||||
Plugin::Flake8Eradicate => vec![CheckCodePrefix::ERA],
|
||||
Plugin::Flake8ErrMsg => vec![CheckCodePrefix::EM],
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T2],
|
||||
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
|
||||
Plugin::Flake8Return => vec![CheckCodePrefix::RET],
|
||||
Plugin::Flake8TidyImports => vec![CheckCodePrefix::I25],
|
||||
Plugin::Flake8Simplify => vec![CheckCodePrefix::SIM],
|
||||
Plugin::Flake8TidyImports => vec![CheckCodePrefix::TID],
|
||||
Plugin::McCabe => vec![CheckCodePrefix::C9],
|
||||
Plugin::PandasVet => vec![CheckCodePrefix::PD],
|
||||
Plugin::PEP8Naming => vec![CheckCodePrefix::N],
|
||||
Plugin::Pyupgrade => vec![CheckCodePrefix::U],
|
||||
Plugin::Pyupgrade => vec![CheckCodePrefix::UP],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,6 +212,7 @@ impl DocstringConvention {
|
||||
// CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
@@ -209,6 +260,7 @@ impl DocstringConvention {
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
// CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
@@ -257,6 +309,7 @@ impl DocstringConvention {
|
||||
CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
// CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
@@ -370,6 +423,9 @@ pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> V
|
||||
"staticmethod-decorators" | "staticmethod_decorators" => {
|
||||
plugins.insert(Plugin::PEP8Naming);
|
||||
}
|
||||
"max-string-length" | "max_string_length" => {
|
||||
plugins.insert(Plugin::Flake8ErrMsg);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -388,15 +444,18 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
Plugin::Flake8Bugbear,
|
||||
Plugin::Flake8Builtins,
|
||||
Plugin::Flake8Comprehensions,
|
||||
Plugin::Flake8Datetimez,
|
||||
Plugin::Flake8Debugger,
|
||||
Plugin::Flake8Docstrings,
|
||||
Plugin::Flake8Eradicate,
|
||||
Plugin::Flake8ErrMsg,
|
||||
Plugin::Flake8Print,
|
||||
Plugin::Flake8Quotes,
|
||||
Plugin::Flake8Return,
|
||||
Plugin::Flake8Simplify,
|
||||
Plugin::Flake8TidyImports,
|
||||
Plugin::PandasVet,
|
||||
Plugin::PEP8Naming,
|
||||
Plugin::Pyupgrade,
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|plugin| {
|
||||
|
||||
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.*
|
||||
1
playground/.prettierignore
Normal file
1
playground/.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
src/ruff_options.ts
|
||||
10
playground/README.md
Normal file
10
playground/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 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`.
|
||||
29
playground/index.html
Normal file
29
playground/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!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>"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div style="display: flex; position: fixed; right: 16px; top: 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>
|
||||
5870
playground/package-lock.json
generated
Normal file
5870
playground/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
playground/package.json
Normal file
38
playground/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"prettier": "^2.8.1",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^4.0.0"
|
||||
}
|
||||
}
|
||||
200
playground/src/App.tsx
Normal file
200
playground/src/App.tsx
Normal file
@@ -0,0 +1,200 @@
|
||||
import lzstring from "lz-string";
|
||||
import Editor, { useMonaco } from "@monaco-editor/react";
|
||||
import { MarkerSeverity } from "monaco-editor/esm/vs/editor/editor.api";
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
|
||||
import init, { Check, check } from "./pkg/ruff.js";
|
||||
import { AVAILABLE_OPTIONS } from "./ruff_options";
|
||||
import { Config, getDefaultConfig, toRuffConfig } from "./config";
|
||||
import { Options } from "./Options";
|
||||
|
||||
const DEFAULT_SOURCE =
|
||||
"# Define a function that takes an integer n and returns the nth number in the Fibonacci\n" +
|
||||
"# sequence.\n" +
|
||||
"def fibonacci(n):\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" +
|
||||
"# 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";
|
||||
|
||||
function restoreConfigAndSource(): [Config, string] {
|
||||
const value = lzstring.decompressFromEncodedURIComponent(
|
||||
window.location.hash.slice(1)
|
||||
);
|
||||
let config = {};
|
||||
let source = DEFAULT_SOURCE;
|
||||
|
||||
if (value) {
|
||||
const parts = value.split("$$$");
|
||||
config = JSON.parse(parts[0]);
|
||||
source = parts[1];
|
||||
}
|
||||
|
||||
return [config, source];
|
||||
}
|
||||
|
||||
function persistConfigAndSource(config: Config, source: string) {
|
||||
window.location.hash = lzstring.compressToEncodedURIComponent(
|
||||
JSON.stringify(config) + "$$$" + source
|
||||
);
|
||||
}
|
||||
|
||||
const defaultConfig = getDefaultConfig(AVAILABLE_OPTIONS);
|
||||
|
||||
export default function App() {
|
||||
const monaco = useMonaco();
|
||||
const [initialized, setInitialized] = useState<boolean>(false);
|
||||
const [config, setConfig] = useState<Config | null>(null);
|
||||
const [source, setSource] = useState<string | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
init().then(() => setInitialized(true));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (source == null && config == null && monaco) {
|
||||
const [config, source] = restoreConfigAndSource();
|
||||
setConfig(config);
|
||||
setSource(source);
|
||||
}
|
||||
}, [monaco, source, config]);
|
||||
|
||||
useEffect(() => {
|
||||
if (config != null && source != null) {
|
||||
persistConfigAndSource(config, source);
|
||||
}
|
||||
}, [config, source]);
|
||||
|
||||
useEffect(() => {
|
||||
const editor = monaco?.editor;
|
||||
const model = editor?.getModels()[0];
|
||||
if (!editor || !model || !initialized || source == null || config == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let checks: Check[];
|
||||
try {
|
||||
checks = check(source, toRuffConfig(config));
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
setError(String(e));
|
||||
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,
|
||||
}))
|
||||
);
|
||||
|
||||
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();
|
||||
};
|
||||
}, [config, source, monaco, initialized]);
|
||||
|
||||
const handleEditorChange = useCallback(
|
||||
(value: string | undefined) => {
|
||||
setSource(value || "");
|
||||
},
|
||||
[setSource]
|
||||
);
|
||||
|
||||
const handleOptionChange = useCallback(
|
||||
(groupName: string, fieldName: string, value: string) => {
|
||||
const group = Object.assign({}, (config || {})[groupName]);
|
||||
if (value === defaultConfig[groupName][fieldName] || value === "") {
|
||||
delete group[fieldName];
|
||||
} else {
|
||||
group[fieldName] = value;
|
||||
}
|
||||
|
||||
setConfig({
|
||||
...config,
|
||||
[groupName]: group,
|
||||
});
|
||||
},
|
||||
[config]
|
||||
);
|
||||
|
||||
return (
|
||||
<div id="app">
|
||||
<Options
|
||||
config={config}
|
||||
defaultConfig={defaultConfig}
|
||||
onChange={handleOptionChange}
|
||||
/>
|
||||
<Editor
|
||||
options={{ readOnly: false, minimap: { enabled: false } }}
|
||||
wrapperProps={{ className: "editor" }}
|
||||
defaultLanguage="python"
|
||||
value={source || ""}
|
||||
theme={"light"}
|
||||
onChange={handleEditorChange}
|
||||
/>
|
||||
{error && <div id="error">{error}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
72
playground/src/Options.tsx
Normal file
72
playground/src/Options.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Config } from "./config";
|
||||
import { AVAILABLE_OPTIONS } from "./ruff_options";
|
||||
|
||||
function OptionEntry({
|
||||
config,
|
||||
defaultConfig,
|
||||
groupName,
|
||||
fieldName,
|
||||
onChange,
|
||||
}: {
|
||||
config: Config | null;
|
||||
defaultConfig: Config;
|
||||
groupName: string;
|
||||
fieldName: string;
|
||||
onChange: (groupName: string, fieldName: string, value: string) => void;
|
||||
}) {
|
||||
const value =
|
||||
config && config[groupName] && config[groupName][fieldName]
|
||||
? config[groupName][fieldName]
|
||||
: "";
|
||||
|
||||
return (
|
||||
<span>
|
||||
<label>
|
||||
{fieldName}
|
||||
<input
|
||||
value={value}
|
||||
placeholder={defaultConfig[groupName][fieldName]}
|
||||
type="text"
|
||||
onChange={(event) => {
|
||||
onChange(groupName, fieldName, event.target.value);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function Options({
|
||||
config,
|
||||
defaultConfig,
|
||||
onChange,
|
||||
}: {
|
||||
config: Config | null;
|
||||
defaultConfig: Config;
|
||||
onChange: (groupName: string, fieldName: string, value: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="options">
|
||||
{AVAILABLE_OPTIONS.map((group) => (
|
||||
<details key={group.name}>
|
||||
<summary>{group.name}</summary>
|
||||
<div>
|
||||
<ul>
|
||||
{group.fields.map((field) => (
|
||||
<li key={field.name}>
|
||||
<OptionEntry
|
||||
config={config}
|
||||
defaultConfig={defaultConfig}
|
||||
groupName={group.name}
|
||||
fieldName={field.name}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
52
playground/src/config.ts
Normal file
52
playground/src/config.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { OptionGroup } from "./ruff_options";
|
||||
|
||||
export type Config = { [key: string]: { [key: string]: string } };
|
||||
|
||||
export function getDefaultConfig(availableOptions: OptionGroup[]): Config {
|
||||
const config: Config = {};
|
||||
availableOptions.forEach((group) => {
|
||||
config[group.name] = {};
|
||||
group.fields.forEach((f) => {
|
||||
config[group.name][f.name] = f.default;
|
||||
});
|
||||
});
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the config in the application to something Ruff accepts.
|
||||
*
|
||||
* Application config is always nested one level. Ruff allows for some
|
||||
* top-level options.
|
||||
*
|
||||
* Any option value is parsed as JSON to convert it to a native JS object.
|
||||
* If that fails, e.g. while a user is typing, we let the application handle that
|
||||
* and show an error.
|
||||
*/
|
||||
export function toRuffConfig(config: Config): any {
|
||||
const convertValue = (value: string): any => {
|
||||
return value === "None" ? null : JSON.parse(value);
|
||||
};
|
||||
|
||||
const result: any = {};
|
||||
Object.keys(config).forEach((group_name) => {
|
||||
const fields = config[group_name];
|
||||
if (!fields || Object.keys(fields).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (group_name === "globals") {
|
||||
Object.keys(fields).forEach((field_name) => {
|
||||
result[field_name] = convertValue(fields[field_name]);
|
||||
});
|
||||
} else {
|
||||
result[group_name] = {};
|
||||
|
||||
Object.keys(fields).forEach((field_name) => {
|
||||
result[group_name][field_name] = convertValue(fields[field_name]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
6
playground/src/custom.d.ts
vendored
Normal file
6
playground/src/custom.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;
|
||||
}
|
||||
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 App from "./App";
|
||||
import "./style.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
239
playground/src/ruff_options.ts
Normal file
239
playground/src/ruff_options.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
|
||||
// This file is auto-generated by `cargo dev generate-playground-options`.
|
||||
export interface OptionGroup {
|
||||
name: string;
|
||||
fields: {
|
||||
name: string;
|
||||
default: string;
|
||||
type: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const AVAILABLE_OPTIONS: OptionGroup[] = [
|
||||
{"name": "globals", "fields": [
|
||||
{
|
||||
"name": "allowed-confusables",
|
||||
"default": '[]',
|
||||
"type": 'Vec<char>',
|
||||
},
|
||||
{
|
||||
"name": "dummy-variable-rgx",
|
||||
"default": '"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"',
|
||||
"type": 'Regex',
|
||||
},
|
||||
{
|
||||
"name": "extend-ignore",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "extend-select",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "external",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "fix-only",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "ignore",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "line-length",
|
||||
"default": '88',
|
||||
"type": 'usize',
|
||||
},
|
||||
{
|
||||
"name": "required-version",
|
||||
"default": 'None',
|
||||
"type": 'String',
|
||||
},
|
||||
{
|
||||
"name": "select",
|
||||
"default": '["E", "F"]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "target-version",
|
||||
"default": '"py310"',
|
||||
"type": 'PythonVersion',
|
||||
},
|
||||
{
|
||||
"name": "unfixable",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-annotations", "fields": [
|
||||
{
|
||||
"name": "allow-star-arg-any",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "mypy-init-return",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "suppress-dummy-args",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "suppress-none-returning",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-bugbear", "fields": [
|
||||
{
|
||||
"name": "extend-immutable-calls",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-errmsg", "fields": [
|
||||
{
|
||||
"name": "max-string-length",
|
||||
"default": '0',
|
||||
"type": 'usize',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-import-conventions", "fields": [
|
||||
{
|
||||
"name": "aliases",
|
||||
"default": '{"altair": "alt", "matplotlib.pyplot": "plt", "numpy": "np", "pandas": "pd", "seaborn": "sns"}',
|
||||
"type": 'FxHashMap<String, String>',
|
||||
},
|
||||
{
|
||||
"name": "extend-aliases",
|
||||
"default": '{}',
|
||||
"type": 'FxHashMap<String, String>',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-quotes", "fields": [
|
||||
{
|
||||
"name": "avoid-escape",
|
||||
"default": 'true',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "docstring-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
{
|
||||
"name": "inline-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
{
|
||||
"name": "multiline-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-tidy-imports", "fields": [
|
||||
{
|
||||
"name": "ban-relative-imports",
|
||||
"default": '"parents"',
|
||||
"type": 'Strictness',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-unused-arguments", "fields": [
|
||||
{
|
||||
"name": "ignore-variadic-names",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "isort", "fields": [
|
||||
{
|
||||
"name": "combine-as-imports",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "extra-standard-library",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "force-single-line",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "force-wrap-aliases",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "known-first-party",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "known-third-party",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "single-line-exclusions",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "split-on-trailing-comma",
|
||||
"default": 'true',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "mccabe", "fields": [
|
||||
{
|
||||
"name": "max-complexity",
|
||||
"default": '10',
|
||||
"type": 'usize',
|
||||
},
|
||||
]},
|
||||
{"name": "pep8-naming", "fields": [
|
||||
{
|
||||
"name": "classmethod-decorators",
|
||||
"default": '["classmethod"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "ignore-names",
|
||||
"default": '["setUp", "tearDown", "setUpClass", "tearDownClass", "setUpModule", "tearDownModule", "asyncSetUp", "asyncTearDown", "setUpTestData", "failureException", "longMessage", "maxDiff"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "staticmethod-decorators",
|
||||
"default": '["staticmethod"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
]},
|
||||
{"name": "pydocstyle", "fields": [
|
||||
{
|
||||
"name": "convention",
|
||||
"default": '"convention"',
|
||||
"type": 'Convention',
|
||||
},
|
||||
]},
|
||||
{"name": "pyupgrade", "fields": [
|
||||
{
|
||||
"name": "keep-runtime-typing",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
];
|
||||
60
playground/src/style.css
Normal file
60
playground/src/style.css
Normal file
@@ -0,0 +1,60 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
html,
|
||||
#root,
|
||||
#app {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.options {
|
||||
height: 100vh;
|
||||
overflow-y: scroll;
|
||||
padding: 1em;
|
||||
min-width: 300px;
|
||||
border-right: 1px solid lightgray;
|
||||
}
|
||||
|
||||
.options ul {
|
||||
padding-left: 1em;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.options li {
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.options details {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.options summary {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.options input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.editor {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#error {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
min-height: 1em;
|
||||
padding: 1em;
|
||||
background: darkred;
|
||||
color: white;
|
||||
}
|
||||
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" />
|
||||
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()],
|
||||
});
|
||||
@@ -12,6 +12,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
@@ -31,3 +32,14 @@ build-backend = "maturin"
|
||||
[tool.maturin]
|
||||
bindings = "bin"
|
||||
strip = true
|
||||
|
||||
[tool.ruff]
|
||||
|
||||
[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"
|
||||
|
||||
3
resources/test/fixtures/README.md
vendored
Normal file
3
resources/test/fixtures/README.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# fixtures
|
||||
|
||||
Fixture files used for snapshot testing.
|
||||
4
resources/test/fixtures/eradicate/ERA001.py
vendored
4
resources/test/fixtures/eradicate/ERA001.py
vendored
@@ -5,9 +5,11 @@ a = 4
|
||||
#foo(1, 2, 3)
|
||||
|
||||
def foo(x, y, z):
|
||||
contentet = 1 # print('hello')
|
||||
content = 1 # print('hello')
|
||||
print(x, y, z)
|
||||
|
||||
# This is a real comment.
|
||||
#return True
|
||||
return False
|
||||
|
||||
#import os # noqa: ERA001
|
||||
|
||||
49
resources/test/fixtures/flake8_annotations/allow_overload.py
vendored
Normal file
49
resources/test/fixtures/flake8_annotations/allow_overload.py
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
from typing import overload
|
||||
|
||||
|
||||
@overload
|
||||
def foo(i: int) -> "int":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def foo(i: "str") -> "str":
|
||||
...
|
||||
|
||||
|
||||
def foo(i):
|
||||
return i
|
||||
|
||||
|
||||
@overload
|
||||
def bar(i: int) -> "int":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def bar(i: "str") -> "str":
|
||||
...
|
||||
|
||||
|
||||
class X:
|
||||
def bar(i):
|
||||
return i
|
||||
|
||||
|
||||
# TODO(charlie): This third case should raise an error (as in Mypy), because we have a
|
||||
# statement between the interfaces and implementation.
|
||||
@overload
|
||||
def baz(i: int) -> "int":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def baz(i: "str") -> "str":
|
||||
...
|
||||
|
||||
|
||||
x = 1
|
||||
|
||||
|
||||
def baz(i):
|
||||
return i
|
||||
@@ -53,3 +53,11 @@ try:
|
||||
raise e
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise bad
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
@@ -55,3 +55,5 @@ a.get("hello", False)
|
||||
{}.pop(True, False)
|
||||
dict.fromkeys(("world",), True)
|
||||
{}.deploy(True, False)
|
||||
getattr(someobj, attrname, False)
|
||||
mylist.index(True)
|
||||
|
||||
@@ -20,6 +20,8 @@ getattr(foo, "_123abc")
|
||||
getattr(foo, "abc123")
|
||||
getattr(foo, r"abc123")
|
||||
_ = lambda x: getattr(x, "bar")
|
||||
if getattr(x, "bar"):
|
||||
pass
|
||||
|
||||
# Valid setattr usage
|
||||
setattr(foo, bar, None)
|
||||
@@ -28,6 +30,8 @@ setattr(foo, "123abc", None)
|
||||
setattr(foo, r"123\abc", None)
|
||||
setattr(foo, "except", None)
|
||||
_ = lambda x: setattr(x, "bar", 1)
|
||||
if setattr(x, "bar", 1):
|
||||
pass
|
||||
|
||||
# Invalid usage
|
||||
setattr(foo, "bar", None)
|
||||
|
||||
10
resources/test/fixtures/flake8_bugbear/B905.py
vendored
Normal file
10
resources/test/fixtures/flake8_bugbear/B905.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
zip()
|
||||
zip(range(3))
|
||||
zip("a", "b")
|
||||
zip("a", "b", *zip("c"))
|
||||
zip(zip("a"), strict=False)
|
||||
zip(zip("a", strict=True))
|
||||
|
||||
zip(range(3), strict=True)
|
||||
zip("a", "b", strict=False)
|
||||
zip("a", "b", "c", strict=True)
|
||||
21
resources/test/fixtures/flake8_datetimez/DTZ001.py
vendored
Normal file
21
resources/test/fixtures/flake8_datetimez/DTZ001.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import datetime
|
||||
|
||||
# no args
|
||||
datetime.datetime(2000, 1, 1, 0, 0, 0)
|
||||
|
||||
# none args
|
||||
datetime.datetime(2000, 1, 1, 0, 0, 0, 0, None)
|
||||
|
||||
# not none arg
|
||||
datetime.datetime(2000, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)
|
||||
|
||||
# no kwargs
|
||||
datetime.datetime(2000, 1, 1, fold=1)
|
||||
|
||||
# none kwargs
|
||||
datetime.datetime(2000, 1, 1, tzinfo=None)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# no args unqualified
|
||||
datetime(2000, 1, 1, 0, 0, 0)
|
||||
9
resources/test/fixtures/flake8_datetimez/DTZ002.py
vendored
Normal file
9
resources/test/fixtures/flake8_datetimez/DTZ002.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import datetime
|
||||
|
||||
# qualified
|
||||
datetime.datetime.today()
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# unqualified
|
||||
datetime.today()
|
||||
9
resources/test/fixtures/flake8_datetimez/DTZ003.py
vendored
Normal file
9
resources/test/fixtures/flake8_datetimez/DTZ003.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import datetime
|
||||
|
||||
# qualified
|
||||
datetime.datetime.utcnow()
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# unqualified
|
||||
datetime.utcnow()
|
||||
9
resources/test/fixtures/flake8_datetimez/DTZ004.py
vendored
Normal file
9
resources/test/fixtures/flake8_datetimez/DTZ004.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import datetime
|
||||
|
||||
# qualified
|
||||
datetime.datetime.utcfromtimestamp(1234)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# unqualified
|
||||
datetime.utcfromtimestamp(1234)
|
||||
18
resources/test/fixtures/flake8_datetimez/DTZ005.py
vendored
Normal file
18
resources/test/fixtures/flake8_datetimez/DTZ005.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import datetime
|
||||
|
||||
# no args
|
||||
datetime.datetime.now()
|
||||
|
||||
# wrong keywords
|
||||
datetime.datetime.now(bad=datetime.timezone.utc)
|
||||
|
||||
# none args
|
||||
datetime.datetime.now(None)
|
||||
|
||||
# none keywords
|
||||
datetime.datetime.now(tz=None)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# no args unqualified
|
||||
datetime.now()
|
||||
18
resources/test/fixtures/flake8_datetimez/DTZ006.py
vendored
Normal file
18
resources/test/fixtures/flake8_datetimez/DTZ006.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import datetime
|
||||
|
||||
# no args
|
||||
datetime.datetime.fromtimestamp(1234)
|
||||
|
||||
# wrong keywords
|
||||
datetime.datetime.fromtimestamp(1234, bad=datetime.timezone.utc)
|
||||
|
||||
# none args
|
||||
datetime.datetime.fromtimestamp(1234, None)
|
||||
|
||||
# none keywords
|
||||
datetime.datetime.fromtimestamp(1234, tz=None)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# no args unqualified
|
||||
datetime.fromtimestamp(1234)
|
||||
35
resources/test/fixtures/flake8_datetimez/DTZ007.py
vendored
Normal file
35
resources/test/fixtures/flake8_datetimez/DTZ007.py
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import datetime
|
||||
|
||||
# bad format
|
||||
datetime.datetime.strptime("something", "%H:%M:%S%Z")
|
||||
|
||||
# no replace or astimezone
|
||||
datetime.datetime.strptime("something", "something")
|
||||
|
||||
# wrong replace
|
||||
datetime.datetime.strptime("something", "something").replace(hour=1)
|
||||
|
||||
# none replace
|
||||
datetime.datetime.strptime("something", "something").replace(tzinfo=None)
|
||||
|
||||
# OK
|
||||
datetime.datetime.strptime("something", "something").replace(
|
||||
tzinfo=datetime.timezone.utc
|
||||
)
|
||||
|
||||
# OK
|
||||
datetime.datetime.strptime("something", "something").astimezone()
|
||||
|
||||
# OK
|
||||
datetime.datetime.strptime("something", "%H:%M:%S%z")
|
||||
|
||||
# OK
|
||||
datetime.datetime.strptime("something", something).astimezone()
|
||||
|
||||
# OK
|
||||
datetime.datetime.strptime("something", something).replace(tzinfo=datetime.timezone.utc)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
# no replace orastimezone unqualified
|
||||
datetime.strptime("something", "something")
|
||||
9
resources/test/fixtures/flake8_datetimez/DTZ011.py
vendored
Normal file
9
resources/test/fixtures/flake8_datetimez/DTZ011.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import datetime
|
||||
|
||||
# qualified
|
||||
datetime.date.today()
|
||||
|
||||
from datetime import date
|
||||
|
||||
# unqualified
|
||||
date.today()
|
||||
9
resources/test/fixtures/flake8_datetimez/DTZ012.py
vendored
Normal file
9
resources/test/fixtures/flake8_datetimez/DTZ012.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import datetime
|
||||
|
||||
# qualified
|
||||
datetime.date.fromtimestamp(1234)
|
||||
|
||||
from datetime import date
|
||||
|
||||
# unqualified
|
||||
date.fromtimestamp(1234)
|
||||
@@ -1,14 +1,13 @@
|
||||
breakpoint()
|
||||
|
||||
|
||||
import pdb
|
||||
import builtins
|
||||
from builtins import breakpoint
|
||||
from pdb import set_trace as st
|
||||
from celery.contrib.rdb import set_trace
|
||||
from celery.contrib import rdb
|
||||
import celery.contrib.rdb
|
||||
|
||||
|
||||
breakpoint()
|
||||
st()
|
||||
set_trace()
|
||||
23
resources/test/fixtures/flake8_errmsg/EM.py
vendored
Normal file
23
resources/test/fixtures/flake8_errmsg/EM.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def f_a():
|
||||
raise RuntimeError("This is an example exception")
|
||||
|
||||
|
||||
def f_a_short():
|
||||
raise RuntimeError("Error")
|
||||
|
||||
|
||||
def f_b():
|
||||
example = "example"
|
||||
raise RuntimeError(f"This is an {example} exception")
|
||||
|
||||
|
||||
def f_c():
|
||||
raise RuntimeError("This is an {example} exception".format(example="example"))
|
||||
|
||||
|
||||
def f_ok():
|
||||
msg = "hello"
|
||||
raise RuntimeError(msg)
|
||||
25
resources/test/fixtures/flake8_import_conventions/custom.py
vendored
Normal file
25
resources/test/fixtures/flake8_import_conventions/custom.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import math # not checked
|
||||
|
||||
import altair # unconventional
|
||||
import dask.array # unconventional
|
||||
import dask.dataframe # unconventional
|
||||
import matplotlib.pyplot # unconventional
|
||||
import numpy # unconventional
|
||||
import pandas # unconventional
|
||||
import seaborn # unconventional
|
||||
|
||||
import altair as altr # unconventional
|
||||
import matplotlib.pyplot as plot # unconventional
|
||||
import dask.array as darray # unconventional
|
||||
import dask.dataframe as ddf # unconventional
|
||||
import numpy as nmp # unconventional
|
||||
import pandas as pdas # unconventional
|
||||
import seaborn as sbrn # unconventional
|
||||
|
||||
import altair as alt # conventional
|
||||
import dask.array as da # conventional
|
||||
import dask.dataframe as dd # conventional
|
||||
import matplotlib.pyplot as plt # conventional
|
||||
import numpy as np # conventional
|
||||
import pandas as pd # conventional
|
||||
import seaborn as sns # conventional
|
||||
19
resources/test/fixtures/flake8_import_conventions/defaults.py
vendored
Normal file
19
resources/test/fixtures/flake8_import_conventions/defaults.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import math # not checked
|
||||
|
||||
import altair # unconventional
|
||||
import matplotlib.pyplot # unconventional
|
||||
import numpy # unconventional
|
||||
import pandas # unconventional
|
||||
import seaborn # unconventional
|
||||
|
||||
import altair as altr # unconventional
|
||||
import matplotlib.pyplot as plot # unconventional
|
||||
import numpy as nmp # unconventional
|
||||
import pandas as pdas # unconventional
|
||||
import seaborn as sbrn # unconventional
|
||||
|
||||
import altair as alt # conventional
|
||||
import matplotlib.pyplot as plt # conventional
|
||||
import numpy as np # conventional
|
||||
import pandas as pd # conventional
|
||||
import seaborn as sns # conventional
|
||||
19
resources/test/fixtures/flake8_import_conventions/override_default.py
vendored
Normal file
19
resources/test/fixtures/flake8_import_conventions/override_default.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import math # not checked
|
||||
|
||||
import altair # unconventional
|
||||
import matplotlib.pyplot # unconventional
|
||||
import numpy # unconventional
|
||||
import pandas # unconventional
|
||||
import seaborn # unconventional
|
||||
|
||||
import altair as altr # unconventional
|
||||
import matplotlib.pyplot as plot # unconventional
|
||||
import numpy as np # unconventional
|
||||
import pandas as pdas # unconventional
|
||||
import seaborn as sbrn # unconventional
|
||||
|
||||
import altair as alt # conventional
|
||||
import matplotlib.pyplot as plt # conventional
|
||||
import numpy as nmp # conventional
|
||||
import pandas as pd # conventional
|
||||
import seaborn as sns # conventional
|
||||
19
resources/test/fixtures/flake8_import_conventions/remove_default.py
vendored
Normal file
19
resources/test/fixtures/flake8_import_conventions/remove_default.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import math # not checked
|
||||
|
||||
import altair # unconventional
|
||||
import matplotlib.pyplot # unconventional
|
||||
import numpy # not checked
|
||||
import pandas # unconventional
|
||||
import seaborn # unconventional
|
||||
|
||||
import altair as altr # unconventional
|
||||
import matplotlib.pyplot as plot # unconventional
|
||||
import numpy as nmp # not checked
|
||||
import pandas as pdas # unconventional
|
||||
import seaborn as sbrn # unconventional
|
||||
|
||||
import altair as alt # conventional
|
||||
import matplotlib.pyplot as plt # conventional
|
||||
import numpy as np # not checked
|
||||
import pandas as pd # conventional
|
||||
import seaborn as sns # conventional
|
||||
9
resources/test/fixtures/flake8_print/T201.py
vendored
9
resources/test/fixtures/flake8_print/T201.py
vendored
@@ -1 +1,10 @@
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
print("Hello, world!") # T201
|
||||
print("Hello, world!", file=None) # T201
|
||||
print("Hello, world!", file=sys.stdout) # T201
|
||||
print("Hello, world!", file=sys.stderr) # T201
|
||||
|
||||
with tempfile.NamedTemporaryFile() as fp:
|
||||
print("Hello, world!", file=fp) # OK
|
||||
|
||||
1
resources/test/fixtures/flake8_print/T203.py
vendored
1
resources/test/fixtures/flake8_print/T203.py
vendored
@@ -2,7 +2,6 @@ from pprint import pprint
|
||||
|
||||
pprint("Hello, world!") # T203
|
||||
|
||||
|
||||
import pprint
|
||||
|
||||
pprint.pprint("Hello, world!") # T203
|
||||
|
||||
45
resources/test/fixtures/flake8_return/RET504.py
vendored
45
resources/test/fixtures/flake8_return/RET504.py
vendored
@@ -6,18 +6,6 @@ def x():
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
b, a = 1, 2
|
||||
print(b)
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print()
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print(a)
|
||||
@@ -53,7 +41,6 @@ def x():
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issue-641117366
|
||||
def user_agent_username(username=None):
|
||||
|
||||
if not username:
|
||||
return ""
|
||||
|
||||
@@ -130,6 +117,26 @@ def x():
|
||||
return val
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print(f"a={a}")
|
||||
return a
|
||||
|
||||
|
||||
# Considered OK, since functions can have side effects.
|
||||
def x():
|
||||
b, a = 1, 2
|
||||
print(b)
|
||||
return a
|
||||
|
||||
|
||||
# Considered OK, since functions can have side effects.
|
||||
def x():
|
||||
a = 1
|
||||
print()
|
||||
return a
|
||||
|
||||
|
||||
# Test cases for using value for assignment then returning it
|
||||
# See:https://github.com/afonasev/flake8-return/issues/47
|
||||
def resolve_from_url(self, url: str) -> dict:
|
||||
@@ -230,3 +237,15 @@ def close(self):
|
||||
any_failed = True
|
||||
report(traceback.format_exc())
|
||||
return any_failed
|
||||
|
||||
def global_assignment():
|
||||
global X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
def nonlocal_assignment():
|
||||
X = 1
|
||||
def inner():
|
||||
nonlocal X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
12
resources/test/fixtures/flake8_simplify/SIM118.py
vendored
Normal file
12
resources/test/fixtures/flake8_simplify/SIM118.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
key in dict.keys() # SIM118
|
||||
|
||||
foo["bar"] in dict.keys() # SIM118
|
||||
|
||||
foo() in dict.keys() # SIM118
|
||||
|
||||
for key in dict.keys(): # SIM118
|
||||
pass
|
||||
|
||||
for key in list(dict.keys()):
|
||||
if some_property(key):
|
||||
del dict[key]
|
||||
155
resources/test/fixtures/flake8_unused_arguments/ARG.py
vendored
Normal file
155
resources/test/fixtures/flake8_unused_arguments/ARG.py
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
from abc import abstractmethod
|
||||
from typing import overload
|
||||
from typing_extensions import override
|
||||
|
||||
|
||||
###
|
||||
# Unused arguments on functions.
|
||||
###
|
||||
def f(self, x):
|
||||
print("Hello, world!")
|
||||
|
||||
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
|
||||
def f(self, x):
|
||||
...
|
||||
|
||||
|
||||
def f(cls, x):
|
||||
...
|
||||
|
||||
|
||||
###
|
||||
# Unused arguments on lambdas.
|
||||
###
|
||||
lambda x: print("Hello, world!")
|
||||
|
||||
|
||||
class C:
|
||||
###
|
||||
# Unused arguments.
|
||||
###
|
||||
def f(self, x):
|
||||
print("Hello, world!")
|
||||
|
||||
def f(self, /, x):
|
||||
print("Hello, world!")
|
||||
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@classmethod
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
def f(x):
|
||||
print("Hello, world!")
|
||||
|
||||
###
|
||||
# Unused arguments attached to empty functions (OK).
|
||||
###
|
||||
def f(self, x):
|
||||
...
|
||||
|
||||
def f(self, /, x):
|
||||
...
|
||||
|
||||
def f(cls, x):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
def f(cls, x):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def f(cls, x):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def f(x):
|
||||
...
|
||||
|
||||
###
|
||||
# Unused functions attached to abstract methods (OK).
|
||||
###
|
||||
@abstractmethod
|
||||
def f(self, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@abstractmethod
|
||||
def f(self, /, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@abstractmethod
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def f(x):
|
||||
print("Hello, world!")
|
||||
|
||||
###
|
||||
# Unused functions attached to overrides (OK).
|
||||
###
|
||||
@override
|
||||
def f(self, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@override
|
||||
def f(self, /, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@override
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@classmethod
|
||||
@override
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
@override
|
||||
def f(cls, x):
|
||||
print("Hello, world!")
|
||||
|
||||
@staticmethod
|
||||
@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}"
|
||||
14
resources/test/fixtures/flake8_unused_arguments/ignore_variadic_names.py
vendored
Normal file
14
resources/test/fixtures/flake8_unused_arguments/ignore_variadic_names.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
def f(a, b):
|
||||
print("Hello, world!")
|
||||
|
||||
|
||||
def f(a, b, *args, **kwargs):
|
||||
print("Hello, world!")
|
||||
|
||||
|
||||
class C:
|
||||
def f(self, a, b):
|
||||
print("Hello, world!")
|
||||
|
||||
def f(self, a, b, *args, **kwargs):
|
||||
print("Hello, world!")
|
||||
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
|
||||
)
|
||||
3
resources/test/fixtures/isort/force_wrap_aliases.py
vendored
Normal file
3
resources/test/fixtures/isort/force_wrap_aliases.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
from .a import a1 as a1, a2 as a2
|
||||
from .b import b1 as b1
|
||||
from .c import c1
|
||||
65
resources/test/fixtures/isort/insert_empty_lines.py
vendored
Normal file
65
resources/test/fixtures/isort/insert_empty_lines.py
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import a
|
||||
import b
|
||||
x = 1
|
||||
import os
|
||||
import sys
|
||||
def f():
|
||||
pass
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
class X: pass
|
||||
y = 1
|
||||
import os
|
||||
import sys
|
||||
"""Docstring"""
|
||||
|
||||
if True:
|
||||
import os
|
||||
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
if True:
|
||||
import os
|
||||
def f():
|
||||
pass
|
||||
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
class X: pass
|
||||
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
def f(): pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
|
||||
# And another.
|
||||
def f():
|
||||
pass
|
||||
65
resources/test/fixtures/isort/insert_empty_lines.pyi
vendored
Normal file
65
resources/test/fixtures/isort/insert_empty_lines.pyi
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import a
|
||||
import b
|
||||
x = 1
|
||||
import os
|
||||
import sys
|
||||
def f():
|
||||
pass
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
class X: pass
|
||||
y = 1
|
||||
import os
|
||||
import sys
|
||||
"""Docstring"""
|
||||
|
||||
if True:
|
||||
import os
|
||||
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
if True:
|
||||
import os
|
||||
def f():
|
||||
pass
|
||||
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
class X: pass
|
||||
|
||||
if True:
|
||||
x = 1
|
||||
import collections
|
||||
import typing
|
||||
def f(): pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
import os
|
||||
|
||||
# Comment goes here.
|
||||
|
||||
# And another.
|
||||
def f():
|
||||
pass
|
||||
@@ -4,3 +4,10 @@ import os
|
||||
if True:
|
||||
x = 1; import sys
|
||||
import os
|
||||
|
||||
if True:
|
||||
x = 1; \
|
||||
import os
|
||||
|
||||
x = 1; \
|
||||
import os
|
||||
|
||||
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,
|
||||
)
|
||||
1
resources/test/fixtures/isort/no_wrap_star.py
vendored
Normal file
1
resources/test/fixtures/isort/no_wrap_star.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
from .subscription import * # type: ignore # some very long comment explaining why this needs a type ignore
|
||||
6
resources/test/fixtures/isort/preserve_import_star.py
vendored
Normal file
6
resources/test/fixtures/isort/preserve_import_star.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
from some_other_module import some_class
|
||||
from some_other_module import *
|
||||
# Above
|
||||
from some_module import some_class # Aside
|
||||
# Above
|
||||
from some_module import * # Aside
|
||||
10
resources/test/fixtures/isort/skip_file.py
vendored
Normal file
10
resources/test/fixtures/isort/skip_file.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# isort: skip_file
|
||||
import e
|
||||
import f
|
||||
|
||||
# isort: split
|
||||
|
||||
import a
|
||||
import b
|
||||
import c
|
||||
import d
|
||||
9
resources/test/fixtures/isort/split.py
vendored
Normal file
9
resources/test/fixtures/isort/split.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import e
|
||||
import f
|
||||
|
||||
# isort: split
|
||||
|
||||
import a
|
||||
import b
|
||||
import c
|
||||
import d
|
||||
61
resources/test/fixtures/pycodestyle/E40.py
vendored
Normal file
61
resources/test/fixtures/pycodestyle/E40.py
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
#: E401
|
||||
import os, sys
|
||||
#: Okay
|
||||
import os
|
||||
import sys
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from myclass import MyClass
|
||||
from foo.bar.yourclass import YourClass
|
||||
|
||||
import myclass
|
||||
import foo.bar.yourclass
|
||||
#: Okay
|
||||
__all__ = ['abc']
|
||||
|
||||
import foo
|
||||
#: Okay
|
||||
__version__ = "42"
|
||||
|
||||
import foo
|
||||
#: Okay
|
||||
__author__ = "Simon Gomizelj"
|
||||
|
||||
import foo
|
||||
#: Okay
|
||||
try:
|
||||
import foo
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print('imported foo')
|
||||
finally:
|
||||
print('made attempt to import foo')
|
||||
|
||||
import bar
|
||||
#: Okay
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", DeprecationWarning)
|
||||
import foo
|
||||
|
||||
import bar
|
||||
#: Okay
|
||||
if False:
|
||||
import foo
|
||||
elif not True:
|
||||
import bar
|
||||
else:
|
||||
import mwahaha
|
||||
|
||||
import bar
|
||||
#: E402
|
||||
VERSION = '1.2.3'
|
||||
|
||||
import foo
|
||||
#: E402
|
||||
import foo
|
||||
|
||||
a = 1
|
||||
|
||||
import bar
|
||||
5
resources/test/fixtures/pycodestyle/E501.py
vendored
5
resources/test/fixtures/pycodestyle/E501.py
vendored
@@ -55,3 +55,8 @@ sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labor
|
||||
|
||||
# OK
|
||||
# https://loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong.url.com
|
||||
|
||||
# Not OK
|
||||
_ = """
|
||||
Source: https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533
|
||||
"""
|
||||
|
||||
4
resources/test/fixtures/pycodestyle/E721.py
vendored
4
resources/test/fixtures/pycodestyle/E721.py
vendored
@@ -15,7 +15,7 @@ import types
|
||||
if type(res) is not types.ListType:
|
||||
pass
|
||||
#: E721
|
||||
assert type(res) == type(False) or type(res) == type(None)
|
||||
assert type(res) == type(False)
|
||||
#: E721
|
||||
assert type(res) == type([])
|
||||
#: E721
|
||||
@@ -52,3 +52,5 @@ if isinstance(res, types.MethodType):
|
||||
pass
|
||||
if type(a) != type(b) or type(a) == type(ccc):
|
||||
pass
|
||||
|
||||
assert type(res) == type(None)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
def fn() -> None:
|
||||
pass
|
||||
print("Newline present (no W292)")
|
||||
|
||||
0
resources/test/fixtures/pycodestyle/W292_3.py
vendored
Normal file
0
resources/test/fixtures/pycodestyle/W292_3.py
vendored
Normal file
1
resources/test/fixtures/pycodestyle/W292_4.py
vendored
Normal file
1
resources/test/fixtures/pycodestyle/W292_4.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
39
resources/test/fixtures/pycodestyle/constant_literals.py
vendored
Normal file
39
resources/test/fixtures/pycodestyle/constant_literals.py
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
###
|
||||
# Errors
|
||||
###
|
||||
if "abc" is "def": # F632 (fix)
|
||||
pass
|
||||
if "abc" is None: # F632 (fix, but leaves behind unfixable E711)
|
||||
pass
|
||||
if None is "abc": # F632 (fix, but leaves behind unfixable E711)
|
||||
pass
|
||||
if "abc" is False: # F632 (fix, but leaves behind unfixable E712)
|
||||
pass
|
||||
if False is "abc": # F632 (fix, but leaves behind unfixable E712)
|
||||
pass
|
||||
if False == None: # E711, E712 (fix)
|
||||
pass
|
||||
if None == False: # E711, E712 (fix)
|
||||
pass
|
||||
|
||||
###
|
||||
# Unfixable errors
|
||||
###
|
||||
if "abc" == None: # E711
|
||||
pass
|
||||
if None == "abc": # E711
|
||||
pass
|
||||
if "abc" == False: # E712
|
||||
pass
|
||||
if False == "abc": # E712
|
||||
pass
|
||||
|
||||
###
|
||||
# Non-errors
|
||||
###
|
||||
if "def" == "abc":
|
||||
pass
|
||||
if False is None:
|
||||
pass
|
||||
if None is False:
|
||||
pass
|
||||
8
resources/test/fixtures/pydocstyle/D.py
vendored
8
resources/test/fixtures/pydocstyle/D.py
vendored
@@ -571,3 +571,11 @@ def multiline_trailing_and_leading_space():
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@expect('D210: No whitespaces allowed surrounding docstring text')
|
||||
@expect("D400: First line should end with a period (not '\"')")
|
||||
@expect("D415: First line should end with a period, question mark, "
|
||||
"or exclamation point (not '\"')")
|
||||
def endswith_quote():
|
||||
"""Whitespace at the end, but also a quote" """
|
||||
|
||||
73
resources/test/fixtures/pydocstyle/D400.py
vendored
Normal file
73
resources/test/fixtures/pydocstyle/D400.py
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
def f():
|
||||
"Here's a line without a period"
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a line without a period"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""
|
||||
Here's a line without a period,
|
||||
but here's the next line
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a line without a period"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""
|
||||
Here's a line without a period,
|
||||
but here's the next line"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""
|
||||
Here's a line without a period,
|
||||
but here's the next line with trailing space """
|
||||
...
|
||||
|
||||
|
||||
|
||||
def f():
|
||||
r"Here's a line without a period"
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
r"""Here's a line without a period"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
r"""
|
||||
Here's a line without a period,
|
||||
but here's the next line
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
r"""Here's a line without a period"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
r"""
|
||||
Here's a line without a period,
|
||||
but here's the next line"""
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
r"""
|
||||
Here's a line without a period,
|
||||
but here's the next line with trailing space """
|
||||
...
|
||||
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
|
||||
16
resources/test/fixtures/pyflakes/F401_7.py
vendored
Normal file
16
resources/test/fixtures/pyflakes/F401_7.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"""Test: noqa directives."""
|
||||
|
||||
from module import (
|
||||
A, # noqa: F401
|
||||
B,
|
||||
)
|
||||
|
||||
from module import (
|
||||
A, # noqa: F401
|
||||
B, # noqa: F401
|
||||
)
|
||||
|
||||
from module import (
|
||||
A,
|
||||
B,
|
||||
)
|
||||
3
resources/test/fixtures/pyflakes/F504.py
vendored
3
resources/test/fixtures/pyflakes/F504.py
vendored
@@ -4,3 +4,6 @@ a = "wrong"
|
||||
|
||||
hidden = {"a": "!"}
|
||||
"%(a)s %(c)s" % {"x": 1, **hidden} # Ok (cannot see through splat)
|
||||
|
||||
"%(a)s" % {"a": 1, r"b": "!"} # F504 ("b" not used)
|
||||
"%(a)s" % {'a': 1, u"b": "!"} # F504 ("b" not used)
|
||||
|
||||
1
resources/test/fixtures/pyflakes/F541.py
vendored
1
resources/test/fixtures/pyflakes/F541.py
vendored
@@ -9,3 +9,4 @@ e = (
|
||||
)
|
||||
|
||||
g = f"ghi{123:{45}}"
|
||||
h = "x" "y" f"z"
|
||||
|
||||
13
resources/test/fixtures/pyflakes/F632.py
vendored
13
resources/test/fixtures/pyflakes/F632.py
vendored
@@ -4,5 +4,18 @@ if x is "abc":
|
||||
if 123 is not y:
|
||||
pass
|
||||
|
||||
if 123 is \
|
||||
not y:
|
||||
pass
|
||||
|
||||
if "123" is x < 3:
|
||||
pass
|
||||
|
||||
if "123" != x is 3:
|
||||
pass
|
||||
|
||||
if ("123" != x) is 3:
|
||||
pass
|
||||
|
||||
if "123" != (x is 3):
|
||||
pass
|
||||
|
||||
11
resources/test/fixtures/pyflakes/F811_0.py
vendored
Normal file
11
resources/test/fixtures/pyflakes/F811_0.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
def foo(x):
|
||||
return x
|
||||
|
||||
|
||||
@foo
|
||||
def bar():
|
||||
pass
|
||||
|
||||
|
||||
def bar():
|
||||
pass
|
||||
1
resources/test/fixtures/pyflakes/F811_1.py
vendored
Normal file
1
resources/test/fixtures/pyflakes/F811_1.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import fu as FU, bar as FU
|
||||
8
resources/test/fixtures/pyflakes/F811_10.py
vendored
Normal file
8
resources/test/fixtures/pyflakes/F811_10.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Test that importing a module twice using a nested does not issue a warning."""
|
||||
try:
|
||||
if True:
|
||||
if True:
|
||||
import os
|
||||
except:
|
||||
import os
|
||||
os.path
|
||||
9
resources/test/fixtures/pyflakes/F811_11.py
vendored
Normal file
9
resources/test/fixtures/pyflakes/F811_11.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
try:
|
||||
from aa import mixer
|
||||
except AttributeError:
|
||||
from bb import mixer
|
||||
except RuntimeError:
|
||||
from cc import mixer
|
||||
except:
|
||||
from dd import mixer
|
||||
mixer(123)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user