Compare commits
223 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58aac21a36 | ||
|
|
77e0be3464 | ||
|
|
bd08fc359d | ||
|
|
19ad6ab4f5 | ||
|
|
4b2df99e78 | ||
|
|
66975876b2 | ||
|
|
7316b120ba | ||
|
|
fec887e481 | ||
|
|
bdd32c0850 | ||
|
|
10dcd5fd0a | ||
|
|
b922e6ecc8 | ||
|
|
f59799e0c4 | ||
|
|
814ddeb7ea | ||
|
|
9315b9f459 | ||
|
|
113b5a10bf | ||
|
|
fe77fb70a1 | ||
|
|
c3f6170503 | ||
|
|
a46160f0e2 | ||
|
|
9a66cf2ffb | ||
|
|
3205473612 | ||
|
|
0bb8b14ae1 | ||
|
|
9cf4621071 | ||
|
|
bbc9ed1b21 | ||
|
|
517ca2604a | ||
|
|
348ff509c0 | ||
|
|
fb545551f8 | ||
|
|
3b33a431d6 | ||
|
|
bc95690725 | ||
|
|
9dc788d089 | ||
|
|
15f63494a7 | ||
|
|
68668c20e8 | ||
|
|
9462335371 | ||
|
|
3dd6522b4f | ||
|
|
6b935121a7 | ||
|
|
8d9d9b3204 | ||
|
|
0a506eff34 | ||
|
|
7c7489c1dd | ||
|
|
ae90eccb7f | ||
|
|
7a61edbe46 | ||
|
|
59615486d8 | ||
|
|
ce116a80ad | ||
|
|
731fba9006 | ||
|
|
9bcf194fdc | ||
|
|
58949b564e | ||
|
|
6b9e57fb78 | ||
|
|
cb119401a7 | ||
|
|
0b9188011b | ||
|
|
b657d912d9 | ||
|
|
1559671093 | ||
|
|
70a53bf12b | ||
|
|
cd1e07f37c | ||
|
|
7bd6db62d9 | ||
|
|
f8b49f308d | ||
|
|
b1f9c7b6bd | ||
|
|
0867d2ded9 | ||
|
|
3f597a3b30 | ||
|
|
6733aad216 | ||
|
|
89980ad651 | ||
|
|
38f896502a | ||
|
|
7cab541343 | ||
|
|
1a3d2ead41 | ||
|
|
f96c64b40d | ||
|
|
0791869451 | ||
|
|
965918744b | ||
|
|
6b4aedb366 | ||
|
|
8123e3e94e | ||
|
|
9f9a545c51 | ||
|
|
5bf8219db3 | ||
|
|
529513bf02 | ||
|
|
124782771f | ||
|
|
98cab5cdba | ||
|
|
40f38c94a5 | ||
|
|
7839204bf7 | ||
|
|
e63ea704f0 | ||
|
|
4be09b45ea | ||
|
|
13e8ed0a0a | ||
|
|
4161d4ae32 | ||
|
|
99f7854d8c | ||
|
|
a580d1a858 | ||
|
|
86806a9e39 | ||
|
|
89afc9db74 | ||
|
|
0f34cdb7a3 | ||
|
|
437b6f23b9 | ||
|
|
0fe2b15676 | ||
|
|
e81efa5a3d | ||
|
|
49559da54e | ||
|
|
b74fd1fe13 | ||
|
|
9c4d24a452 | ||
|
|
7a4449eacb | ||
|
|
ee31fa6109 | ||
|
|
6ffe767252 | ||
|
|
2f894e3951 | ||
|
|
589d923c99 | ||
|
|
c5722d8a4d | ||
|
|
c2d6307e9b | ||
|
|
f44fada446 | ||
|
|
6a6f4651aa | ||
|
|
66ae4db6cd | ||
|
|
801c76037f | ||
|
|
ab825eb28d | ||
|
|
826ef7da67 | ||
|
|
72f5393d3a | ||
|
|
6602f7f489 | ||
|
|
aafddae644 | ||
|
|
749df87de0 | ||
|
|
d67db33f22 | ||
|
|
f0a54716e5 | ||
|
|
c59e1ff0b5 | ||
|
|
ecf858cf16 | ||
|
|
8063aee006 | ||
|
|
f1fee5d240 | ||
|
|
d3155560df | ||
|
|
90bfc4ec4d | ||
|
|
b04a6a3f7c | ||
|
|
8ec14e7ee2 | ||
|
|
17c5cd7c42 | ||
|
|
7d8360a1de | ||
|
|
910ee523dd | ||
|
|
72e35a535e | ||
|
|
b4e1563517 | ||
|
|
5717cc97d7 | ||
|
|
2c89a19f76 | ||
|
|
82fea36bb3 | ||
|
|
63d63e8c12 | ||
|
|
9d136de55a | ||
|
|
1821c07367 | ||
|
|
1fe90ef7f4 | ||
|
|
b5cb9485f6 | ||
|
|
4d798512b1 | ||
|
|
5f9815b103 | ||
|
|
0d3fac1bf9 | ||
|
|
ff0e5f5cb4 | ||
|
|
374d57d822 | ||
|
|
85b2a9920f | ||
|
|
3c22913470 | ||
|
|
ea03a59b72 | ||
|
|
058a5276b0 | ||
|
|
62d4096be3 | ||
|
|
8961da7b89 | ||
|
|
58bcffbe2d | ||
|
|
f67727b13c | ||
|
|
fea029ae35 | ||
|
|
3e3c3c7421 | ||
|
|
9047bf680d | ||
|
|
d170388b7b | ||
|
|
502d3316f9 | ||
|
|
a8159f9893 | ||
|
|
71f727c380 | ||
|
|
ce3c45a361 | ||
|
|
29ae6c159d | ||
|
|
1ae07b4c70 | ||
|
|
08ca8788a7 | ||
|
|
8a97a76038 | ||
|
|
d2d84cf5bf | ||
|
|
450970e0e6 | ||
|
|
34ecc69914 | ||
|
|
a310aed128 | ||
|
|
43cc8bc84e | ||
|
|
84bf36194b | ||
|
|
e4d168bb4f | ||
|
|
439642addf | ||
|
|
f5b1f957e3 | ||
|
|
8f99705795 | ||
|
|
9ec7e6bcd6 | ||
|
|
695b06ba60 | ||
|
|
3a2e6926d4 | ||
|
|
d16c3a1186 | ||
|
|
53a2187f02 | ||
|
|
00b5d1059c | ||
|
|
b7acf76aaf | ||
|
|
8cfc0e5cf5 | ||
|
|
aa7681f9ad | ||
|
|
2493d48725 | ||
|
|
1b422a7f12 | ||
|
|
da051624e4 | ||
|
|
da9ae6a42a | ||
|
|
afa59d78bb | ||
|
|
bbc38fea73 | ||
|
|
6bcc11a90f | ||
|
|
6f36e5dd25 | ||
|
|
1d13752eb1 | ||
|
|
394af0dcff | ||
|
|
51cee471a0 | ||
|
|
8df3a5437a | ||
|
|
a21fe716f2 | ||
|
|
558883299a | ||
|
|
048a13c795 | ||
|
|
5a8b7c1d20 | ||
|
|
f8932ec12b | ||
|
|
2e7878ff48 | ||
|
|
5113ded22a | ||
|
|
bf7bf7aa17 | ||
|
|
560c00ff9d | ||
|
|
befe64a10e | ||
|
|
4eccfdeb69 | ||
|
|
4123ba9851 | ||
|
|
e727c24f79 | ||
|
|
bd3b40688f | ||
|
|
b5549382a7 | ||
|
|
8cf745045f | ||
|
|
f6992cc98c | ||
|
|
3cc74c0564 | ||
|
|
887b9aa840 | ||
|
|
faf8556a5c | ||
|
|
1888f6d41b | ||
|
|
9d8cd2d2fe | ||
|
|
05c19f0091 | ||
|
|
8213b64ad5 | ||
|
|
ff0f5968fa | ||
|
|
6c17670aa5 | ||
|
|
1347b7ebb6 | ||
|
|
f40609f524 | ||
|
|
f572acab30 | ||
|
|
1eb5f3ea75 | ||
|
|
24aa177912 | ||
|
|
2ddc768412 | ||
|
|
0f9508f549 | ||
|
|
7c3d387abd | ||
|
|
d600650214 | ||
|
|
43383bb696 | ||
|
|
ff83f356af | ||
|
|
89622425d4 | ||
|
|
1aafe31c00 |
7
.github/workflows/ci.yaml
vendored
7
.github/workflows/ci.yaml
vendored
@@ -6,6 +6,11 @@ on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
cargo_build:
|
||||
name: "cargo build"
|
||||
@@ -77,7 +82,7 @@ jobs:
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: cargo clippy --all -- -D warnings
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
|
||||
|
||||
cargo_test:
|
||||
name: "cargo test"
|
||||
|
||||
11
.github/workflows/flake8-to-ruff.yaml
vendored
11
.github/workflows/flake8-to-ruff.yaml
vendored
@@ -10,6 +10,9 @@ env:
|
||||
PACKAGE_NAME: flake8-to-ruff
|
||||
CRATE_NAME: flake8_to_ruff
|
||||
PYTHON_VERSION: "3.7" # to build abi3 wheels
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
macos-x86_64:
|
||||
@@ -31,7 +34,6 @@ jobs:
|
||||
with:
|
||||
target: x86_64
|
||||
args: --release --out dist --sdist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel - x86_64
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
|
||||
@@ -58,7 +60,6 @@ jobs:
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
args: --release --universal2 --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel - universal2
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*universal2.whl --force-reinstall
|
||||
@@ -90,7 +91,6 @@ jobs:
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -118,7 +118,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
@@ -145,7 +144,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- uses: uraimo/run-on-arch-action@v2.0.5
|
||||
if: matrix.target != 'ppc64'
|
||||
name: Install built wheel
|
||||
@@ -184,7 +182,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
uses: addnab/docker-run-action@v3
|
||||
@@ -220,7 +217,6 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
maturin-version: "v0.13.0"
|
||||
- uses: uraimo/run-on-arch-action@master
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -258,7 +254,6 @@ jobs:
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
maturin-version: "v0.13.0"
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
|
||||
17
.github/workflows/ruff.yaml
vendored
17
.github/workflows/ruff.yaml
vendored
@@ -12,6 +12,9 @@ concurrency:
|
||||
env:
|
||||
PACKAGE_NAME: ruff
|
||||
PYTHON_VERSION: "3.7" # to build abi3 wheels
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
macos-x86_64:
|
||||
@@ -33,7 +36,6 @@ jobs:
|
||||
with:
|
||||
target: x86_64
|
||||
args: --release --out dist --sdist
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel - x86_64
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
@@ -60,7 +62,6 @@ jobs:
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
args: --release --universal2 --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel - universal2
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall
|
||||
@@ -92,7 +93,6 @@ jobs:
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -120,7 +120,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
@@ -147,7 +146,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --no-default-features --release --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- uses: uraimo/run-on-arch-action@v2.0.5
|
||||
if: matrix.target != 'ppc64'
|
||||
name: Install built wheel
|
||||
@@ -186,7 +184,6 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
uses: addnab/docker-run-action@v3
|
||||
@@ -222,7 +219,6 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
maturin-version: "v0.13.0"
|
||||
- uses: uraimo/run-on-arch-action@master
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -260,7 +256,6 @@ jobs:
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
maturin-version: "v0.13.0"
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -i pypy${{ matrix.python-version }}
|
||||
@@ -292,10 +287,14 @@ jobs:
|
||||
with:
|
||||
name: wheels
|
||||
- uses: actions/setup-python@v4
|
||||
- name: Publish to PyPi
|
||||
- name: Publish to PyPI
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.RUFF_TOKEN }}
|
||||
run: |
|
||||
pip install --upgrade twine
|
||||
twine upload --skip-existing *
|
||||
- name: Publish to GitHub Releases
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: *
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.106
|
||||
rev: v0.0.136
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
@@ -98,6 +98,13 @@ _and_ a `pyproject.toml` parameter to `src/pyproject.rs`. If you want to pattern
|
||||
existing example, grep for `dummy_variable_rgx`, which defines a regular expression to match against
|
||||
acceptable unused variables (e.g., `_`).
|
||||
|
||||
If the new plugin's configuration should be cached between runs, you'll need to add it to the
|
||||
`Hash` implementation for `Settings` in `src/settings/mod.rs`.
|
||||
|
||||
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
lives in `flake8_to_ruff/src/converter.rs`.
|
||||
|
||||
## Release process
|
||||
|
||||
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub
|
||||
|
||||
931
Cargo.lock
generated
931
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
34
Cargo.toml
34
Cargo.toml
@@ -6,16 +6,21 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.106"
|
||||
version = "0.0.136"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.60" }
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
anyhow = { version = "1.0.66" }
|
||||
atty = { version = "0.2.14" }
|
||||
bincode = { version = "1.3.3" }
|
||||
chrono = { version = "0.4.21" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cachedir = { version = "0.3.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
colored = { version = "2.0.0" }
|
||||
common-path = { version = "1.0.0" }
|
||||
@@ -24,30 +29,31 @@ fern = { version = "0.6.1" }
|
||||
filetime = { version = "0.2.17" }
|
||||
glob = { version = "0.3.0" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "32a044c127668df44582f85699358e67803b0d73" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "a13ec97dd4eb925bde4d426c6e422582793b260c" }
|
||||
log = { version = "0.4.17" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
notify = { version = "4.0.17" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
once_cell = { version = "1.13.1" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
rayon = { version = "1.5.3" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "77b821a1941019fe34f73ce17cea013ae1b98fd0" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "77b821a1941019fe34f73ce17cea013ae1b98fd0" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "77b821a1941019fe34f73ce17cea013ae1b98fd0" }
|
||||
serde = { version = "1.0.143", features = ["derive"] }
|
||||
serde_json = { version = "1.0.83" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
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" }
|
||||
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" }
|
||||
textwrap = { version = "0.15.1" }
|
||||
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 }
|
||||
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]
|
||||
cacache = { version = "10.0.1" } # uses async-std
|
||||
clearscreen = { version = "1.0.10" } # uses which
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
|
||||
424
LICENSE
424
LICENSE
@@ -19,3 +19,427 @@ 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.
|
||||
|
||||
The externally maintained libraries from which parts of the Software is derived
|
||||
are:
|
||||
|
||||
- Pyflakes, licensed as follows:
|
||||
"""
|
||||
Copyright 2005-2011 Divmod, Inc.
|
||||
Copyright 2013-2014 Florent Xicluna
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- autoflake, licensed as follows:
|
||||
"""
|
||||
Copyright (C) 2012-2018 Steven Myint
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- Flake8, licensed as follows:
|
||||
"""
|
||||
== Flake8 License (MIT) ==
|
||||
|
||||
Copyright (C) 2011-2013 Tarek Ziade <tarek@ziade.org>
|
||||
Copyright (C) 2012-2016 Ian Cordasco <graffatcolmingov@gmail.com>
|
||||
|
||||
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-2020, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2019 Anthony Sottile
|
||||
|
||||
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-annotations, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 - Present S. Co1
|
||||
|
||||
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-bandit, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2017 Tyler Wince
|
||||
|
||||
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-blind-except, licensed as follows:
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Elijah Andrews
|
||||
|
||||
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-bugbear, licensed as follows:
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Łukasz Langa
|
||||
|
||||
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-comprehensions, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Adam Johnson
|
||||
|
||||
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-tidy-imports, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Adam Johnson
|
||||
|
||||
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-print, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Joseph Kahn
|
||||
|
||||
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-quotes, licensed as follows:
|
||||
"""
|
||||
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)
|
||||
|
||||
Copyright (c) 2013 Timothy Edmund Crosley
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- pep8-naming, licensed as follows:
|
||||
"""
|
||||
Copyright © 2013 Florent Xicluna <florent.xicluna@gmail.com>
|
||||
|
||||
Licensed under the terms of the Expat License
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- pycodestyle, licensed as follows:
|
||||
"""
|
||||
Copyright © 2006-2009 Johann C. Rocholl <johann@rocholl.net>
|
||||
Copyright © 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
|
||||
Copyright © 2014-2020 Ian Lee <IanLee1521@gmail.com>
|
||||
|
||||
Licensed under the terms of the Expat License
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- pydocstyle, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2012 GreenSteam, <http://greensteam.dk/>
|
||||
|
||||
Copyright (c) 2014-2020 Amir Rachum, <http://amir.rachum.com/>
|
||||
|
||||
Copyright (c) 2020 Sambhav Kothari, <https://github.com/samj1912>
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
- pyupgrade, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2017 Anthony Sottile
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
367
README.md
367
README.md
@@ -27,44 +27,54 @@ An extremely fast Python linter, written in Rust.
|
||||
|
||||
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
|
||||
functionality behind a single, common interface. Ruff can be used to replace Flake8 (plus a variety
|
||||
of plugins), [`pydocstyle`](https://pypi.org/project/pydocstyle/), [`yesqa`](https://github.com/asottile/yesqa),
|
||||
and even a subset of [`pyupgrade`](https://pypi.org/project/pyupgrade/) and [`autoflake`](https://pypi.org/project/autoflake/)
|
||||
all while executing tens or hundreds of times faster than any individual tool.
|
||||
of plugins), [`isort`](https://pypi.org/project/isort/), [`pydocstyle`](https://pypi.org/project/pydocstyle/),
|
||||
[`yesqa`](https://github.com/asottile/yesqa), and even a subset of [`pyupgrade`](https://pypi.org/project/pyupgrade/)
|
||||
and [`autoflake`](https://pypi.org/project/autoflake/) all while executing tens or hundreds of times
|
||||
faster than any individual tool.
|
||||
|
||||
(Coming from Flake8? Try [`flake8-to-ruff`](https://pypi.org/project/flake8-to-ruff/) to
|
||||
automatically convert your existing configuration.)
|
||||
Ruff is actively developed and used in major open-source projects like:
|
||||
|
||||
Ruff is actively developed and used in major open-source projects
|
||||
like [Zulip](https://github.com/zulip/zulip), [pydantic](https://github.com/pydantic/pydantic),
|
||||
and [Saleor](https://github.com/saleor/saleor).
|
||||
- [FastAPI](https://github.com/tiangolo/fastapi)
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [Saleor](https://github.com/saleor/saleor)
|
||||
- [Hatch](https://github.com/pypa/hatch)
|
||||
|
||||
Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Installation and Usage](#installation-and-usage)
|
||||
2. [Configuration](#configuration)
|
||||
3. [Supported Rules](#supported-rules)
|
||||
1. [Pyflakes](#pyflakes)
|
||||
2. [pycodestyle](#pycodestyle)
|
||||
3. [pydocstyle](#pydocstyle)
|
||||
4. [pyupgrade](#pyupgrade)
|
||||
5. [pep8-naming](#pep8-naming)
|
||||
6. [flake8-comprehensions](#flake8-comprehensions)
|
||||
7. [flake8-bugbear](#flake8-bugbear)
|
||||
8. [flake8-builtins](#flake8-builtins)
|
||||
9. [flake8-print](#flake8-print)
|
||||
10. [flake8-quotes](#flake8-quotes)
|
||||
11. [flake8-annotations](#flake8-annotations)
|
||||
12. [Ruff-specific rules](#ruff-specific-rules)
|
||||
13. [Meta rules](#meta-rules)
|
||||
5. [Editor Integrations](#editor-integrations)
|
||||
6. [FAQ](#faq)
|
||||
7. [Development](#development)
|
||||
8. [Releases](#releases)
|
||||
9. [Benchmarks](#benchmarks)
|
||||
10. [License](#license)
|
||||
11. [Contributing](#contributing)
|
||||
1. [Configuration](#configuration)
|
||||
1. [Supported Rules](#supported-rules)
|
||||
1. [Pyflakes (F)](#pyflakes)
|
||||
1. [pycodestyle (E)](#pycodestyle)
|
||||
1. [isort (I)](#isort)
|
||||
1. [pydocstyle (D)](#pydocstyle)
|
||||
1. [pyupgrade (U)](#pyupgrade)
|
||||
1. [pep8-naming (N)](#pep8-naming)
|
||||
1. [flake8-bandit (S)](#flake8-bandit)
|
||||
1. [flake8-comprehensions (C)](#flake8-comprehensions)
|
||||
1. [flake8-bugbear (B)](#flake8-bugbear)
|
||||
1. [flake8-builtins (A)](#flake8-builtins)
|
||||
1. [flake8-tidy-imports (I25)](#flake8-tidy-imports)
|
||||
1. [flake8-print (T)](#flake8-print)
|
||||
1. [flake8-quotes (Q)](#flake8-quotes)
|
||||
1. [flake8-annotations (ANN)](#flake8-annotations)
|
||||
1. [flake8-2020 (YTT)](#flake8-2020)
|
||||
1. [flake8-blind-except (BLE)](#flake8-blind-except)
|
||||
1. [flake8-boolean-trap (FBT)](#flake8-boolean-trap)
|
||||
1. [mccabe (C90)](#mccabe)
|
||||
1. [Ruff-specific rules (RUF)](#ruff-specific-rules)
|
||||
1. [Meta rules (M)](#meta-rules)
|
||||
1. [Editor Integrations](#editor-integrations)
|
||||
1. [FAQ](#faq)
|
||||
1. [Development](#development)
|
||||
1. [Releases](#releases)
|
||||
1. [Benchmarks](#benchmarks)
|
||||
1. [License](#license)
|
||||
1. [Contributing](#contributing)
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
@@ -97,7 +107,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.106
|
||||
rev: v0.0.136
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -114,7 +124,7 @@ default configuration is equivalent to:
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
|
||||
# Enable Flake's "E" and "F" codes by default.
|
||||
# Enable Pyflakes `E` and `F` codes by default.
|
||||
select = ["E", "F"]
|
||||
ignore = []
|
||||
|
||||
@@ -147,20 +157,30 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
# Assume Python 3.10.
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
# Unlike Flake8, default to a complexity level of 10.
|
||||
max-complexity = 10
|
||||
```
|
||||
|
||||
As an example, the following would configure Ruff to (1) avoid checking for line-length
|
||||
violations (`E501`) and (2) ignore unused import rules in `__init__.py` files:
|
||||
As an example, the following would configure Ruff to: (1) avoid checking for line-length
|
||||
violations (`E501`); (2), always autofix, but never remove unused imports (`F401`); and (3) ignore
|
||||
import-at-top-of-file errors (`E402`) in `__init__.py` files:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Enable Pyflakes and pycodestyle rules.
|
||||
select = ["E", "F"]
|
||||
|
||||
# Never enforce `E501`.
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Ignore `F401` violations in any `__init__.py` file, and in `path/to/file.py`.
|
||||
per-file-ignores = {"__init__.py" = ["F401"], "path/to/file.py" = ["F401"]}
|
||||
# Always autofix, but never try to fix `F401` (unused imports).
|
||||
fix = true
|
||||
unfixable = ["F401"]
|
||||
|
||||
# Ignore `E402` (import violations in any `__init__.py` file, and in `path/to/file.py`.
|
||||
per-file-ignores = {"__init__.py" = ["E402"], "path/to/file.py" = ["E402"]}
|
||||
```
|
||||
|
||||
Plugin configurations should be expressed as subsections, e.g.:
|
||||
@@ -183,7 +203,7 @@ ruff path/to/code/ --select F401 --select F403
|
||||
See `ruff --help` for more:
|
||||
|
||||
```shell
|
||||
ruff: An extremely fast Python linter.
|
||||
Ruff: An extremely fast Python linter.
|
||||
|
||||
Usage: ruff [OPTIONS] <FILES>...
|
||||
|
||||
@@ -219,20 +239,30 @@ Options:
|
||||
List of paths, used to exclude files and/or directories from checks
|
||||
--extend-exclude <EXTEND_EXCLUDE>
|
||||
Like --exclude, but adds additional files and directories on top of the excluded ones
|
||||
--fixable <FIXABLE>
|
||||
List of error codes to treat as eligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
--unfixable <UNFIXABLE>
|
||||
List of error codes to treat as ineligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
--per-file-ignores <PER_FILE_IGNORES>
|
||||
List of mappings from file pattern to code to exclude
|
||||
--format <FORMAT>
|
||||
Output serialization format for error messages [default: text] [possible values: text, json]
|
||||
--show-source
|
||||
Show violations with source code
|
||||
--show-files
|
||||
See the files ruff will be run against with the current settings
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
See ruff's settings
|
||||
See Ruff's settings
|
||||
--add-noqa
|
||||
Enable automatic additions of noqa directives to failing lines
|
||||
--dummy-variable-rgx <DUMMY_VARIABLE_RGX>
|
||||
Regular expression matching the name of dummy variables
|
||||
--target-version <TARGET_VERSION>
|
||||
The minimum Python version that should be supported
|
||||
--line-length <LINE_LENGTH>
|
||||
Set the line-length for length-associated checks and automatic formatting
|
||||
--max-complexity <MAX_COMPLEXITY>
|
||||
Max McCabe complexity allowed for a function
|
||||
--stdin-filename <STDIN_FILENAME>
|
||||
The name of the file when passing it through stdin
|
||||
-h, --help
|
||||
@@ -285,16 +315,16 @@ Ruff supports several workflows to aid in `noqa` management.
|
||||
|
||||
First, Ruff provides a special error code, `M001`, to enforce that your `noqa` directives are
|
||||
"valid", in that the errors they _say_ they ignore are actually being triggered on that line (and
|
||||
thus suppressed). **You can run `ruff /path/to/file.py --extend-select M001` to flag unused `noqa`
|
||||
directives.**
|
||||
thus suppressed). You can run `ruff /path/to/file.py --extend-select M001` to flag unused `noqa`
|
||||
directives.
|
||||
|
||||
Second, Ruff can _automatically remove_ unused `noqa` directives via its autofix functionality.
|
||||
**You can run `ruff /path/to/file.py --extend-select M001 --fix` to automatically remove unused
|
||||
`noqa` directives.**
|
||||
You can run `ruff /path/to/file.py --extend-select M001 --fix` to automatically remove unused
|
||||
`noqa` directives.
|
||||
|
||||
Third, Ruff can _automatically add_ `noqa` directives to all failing lines. This is useful when
|
||||
migrating a new codebase to Ruff. **You can run `ruff /path/to/file.py --add-noqa` to automatically
|
||||
add `noqa` directives to all failing lines, with the appropriate error codes.**
|
||||
migrating a new codebase to Ruff. You can run `ruff /path/to/file.py --add-noqa` to automatically
|
||||
add `noqa` directives to all failing lines, with the appropriate error codes.
|
||||
|
||||
## Supported Rules
|
||||
|
||||
@@ -333,7 +363,7 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| F702 | ContinueOutsideLoop | `continue` not properly in loop | |
|
||||
| F704 | YieldOutsideFunction | `yield` or `yield from` statement outside of a function | |
|
||||
| F706 | ReturnOutsideFunction | `return` statement outside of a function/method | |
|
||||
| F707 | DefaultExceptNotLast | An `except:` block as not the last exception handler | |
|
||||
| F707 | DefaultExceptNotLast | An `except` block as not the last exception handler | |
|
||||
| F722 | ForwardAnnotationSyntaxError | Syntax error in forward annotation: `...` | |
|
||||
| F821 | UndefinedName | Undefined name `...` | |
|
||||
| F822 | UndefinedExport | Undefined name `...` in `__all__` | |
|
||||
@@ -350,13 +380,13 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||
| ---- | ---- | ------- | --- |
|
||||
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | |
|
||||
| E501 | LineTooLong | Line too long (89 > 88 characters) | |
|
||||
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | |
|
||||
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` | |
|
||||
| E713 | NotInTest | Test for membership should be `not in` | |
|
||||
| E714 | NotIsTest | Test for object identity should be `is not` | |
|
||||
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | 🛠 |
|
||||
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` | 🛠 |
|
||||
| E713 | NotInTest | Test for membership should be `not in` | 🛠 |
|
||||
| E714 | NotIsTest | Test for object identity should be `is not` | 🛠 |
|
||||
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
|
||||
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
|
||||
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | |
|
||||
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | 🛠 |
|
||||
| E741 | AmbiguousVariableName | Ambiguous variable name: `...` | |
|
||||
| E742 | AmbiguousClassName | Ambiguous class name: `...` | |
|
||||
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
|
||||
@@ -365,6 +395,14 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||
| W292 | NoNewLineAtEndOfFile | No newline at end of file | |
|
||||
| W605 | InvalidEscapeSequence | Invalid escape sequence: '\c' | |
|
||||
|
||||
### isort
|
||||
|
||||
For more, see [isort](https://pypi.org/project/isort/5.10.1/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| I001 | UnsortedImports | Import block is un-sorted or un-formatted | 🛠 |
|
||||
|
||||
### pydocstyle
|
||||
|
||||
For more, see [pydocstyle](https://pypi.org/project/pydocstyle/6.1.1/) on PyPI.
|
||||
@@ -399,7 +437,7 @@ For more, see [pydocstyle](https://pypi.org/project/pydocstyle/6.1.1/) on PyPI.
|
||||
| D400 | EndsInPeriod | First line should end with a period | |
|
||||
| D402 | NoSignature | First line should not be the function's signature | |
|
||||
| D403 | FirstLineCapitalized | First word of the first line should be properly capitalized | |
|
||||
| D404 | NoThisPrefix | First word of the docstring should not be 'This' | |
|
||||
| D404 | NoThisPrefix | First word of the docstring should not be "This" | |
|
||||
| D405 | CapitalizeSectionName | Section name should be properly capitalized ("returns") | 🛠 |
|
||||
| D406 | NewLineAfterSectionName | Section name should end with a newline ("Returns") | 🛠 |
|
||||
| D407 | DashedUnderlineAfterSection | Missing dashed underline after section ("Returns") | 🛠 |
|
||||
@@ -423,14 +461,19 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| U001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
|
||||
| U002 | UnnecessaryAbspath | `abspath(__file__)` is unnecessary in Python 3.9 and later | 🛠 |
|
||||
| U003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
|
||||
| U004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
|
||||
| U005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` instead | 🛠 |
|
||||
| U006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
|
||||
| U007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
|
||||
| U008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | 🛠 |
|
||||
| U009 | PEP3120UnnecessaryCodingComment | utf-8 encoding declaration is unnecessary | 🛠 |
|
||||
| U009 | PEP3120UnnecessaryCodingComment | UTF-8 encoding declaration is unnecessary | 🛠 |
|
||||
| U010 | UnnecessaryFutureImport | Unnecessary `__future__` import `...` for target Python version | 🛠 |
|
||||
| U011 | UnnecessaryLRUCacheParams | Unnecessary parameters to `functools.lru_cache` | 🛠 |
|
||||
| U012 | UnnecessaryEncodeUTF8 | Unnecessary call to `encode` as UTF-8 | 🛠 |
|
||||
| U013 | ConvertTypedDictFunctionalToClass | Convert `...` from `TypedDict` functional to class syntax | 🛠 |
|
||||
| U014 | ConvertNamedTupleFunctionalToClass | Convert `...` from `NamedTuple` functional to class syntax | 🛠 |
|
||||
| U015 | RedundantOpenModes | Unnecessary open mode parameters | 🛠 |
|
||||
|
||||
### pep8-naming
|
||||
|
||||
@@ -454,6 +497,19 @@ For more, see [pep8-naming](https://pypi.org/project/pep8-naming/0.13.2/) on PyP
|
||||
| N817 | CamelcaseImportedAsAcronym | Camelcase `...` imported as acronym `...` | |
|
||||
| N818 | ErrorSuffixOnExceptionName | Exception name `...` should be named with an Error suffix | |
|
||||
|
||||
### flake8-bandit
|
||||
|
||||
For more, see [flake8-bandit](https://pypi.org/project/flake8-bandit/4.1.1/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| S101 | AssertUsed | Use of `assert` detected | |
|
||||
| S102 | ExecUsed | Use of `exec` detected | |
|
||||
| S104 | HardcodedBindAllInterfaces | Possible binding to all interfaces | |
|
||||
| S105 | HardcodedPasswordString | Possible hardcoded password: `"..."` | |
|
||||
| S106 | HardcodedPasswordFuncArg | Possible hardcoded password: `"..."` | |
|
||||
| S107 | HardcodedPasswordDefault | Possible hardcoded password: `"..."` | |
|
||||
|
||||
### flake8-comprehensions
|
||||
|
||||
For more, see [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/3.10.1/) on PyPI.
|
||||
@@ -464,7 +520,7 @@ For more, see [flake8-comprehensions](https://pypi.org/project/flake8-comprehens
|
||||
| C401 | UnnecessaryGeneratorSet | Unnecessary generator (rewrite as a `set` comprehension) | 🛠 |
|
||||
| C402 | UnnecessaryGeneratorDict | Unnecessary generator (rewrite as a `dict` comprehension) | 🛠 |
|
||||
| C403 | UnnecessaryListComprehensionSet | Unnecessary `list` comprehension (rewrite as a `set` comprehension) | 🛠 |
|
||||
| C404 | UnnecessaryListComprehensionDict | Unnecessary `list` comprehension (rewrite as a `dict` comprehension) | |
|
||||
| C404 | UnnecessaryListComprehensionDict | Unnecessary `list` comprehension (rewrite as a `dict` comprehension) | 🛠 |
|
||||
| C405 | UnnecessaryLiteralSet | Unnecessary `(list\|tuple)` literal (rewrite as a `set` literal) | 🛠 |
|
||||
| C406 | UnnecessaryLiteralDict | Unnecessary `(list\|tuple)` literal (rewrite as a `dict` literal) | 🛠 |
|
||||
| C408 | UnnecessaryCollectionCall | Unnecessary `(dict\|list\|tuple)` call (rewrite as a literal) | 🛠 |
|
||||
@@ -477,27 +533,47 @@ For more, see [flake8-comprehensions](https://pypi.org/project/flake8-comprehens
|
||||
| C416 | UnnecessaryComprehension | Unnecessary `(list\|set)` comprehension (rewrite using `(list\|set)()`) | 🛠 |
|
||||
| C417 | UnnecessaryMap | Unnecessary `map` usage (rewrite using a `(list\|set\|dict)` comprehension) | |
|
||||
|
||||
### flake8-boolean-trap
|
||||
|
||||
For more, see [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/0.1.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| FBT001 | BooleanPositionalArgInFunctionDefinition | Boolean positional arg in function definition | |
|
||||
| FBT002 | BooleanDefaultValueInFunctionDefinition | Boolean default value in function definition | |
|
||||
| FBT003 | BooleanPositionalValueInFunctionCall | Boolean positional value in function call | |
|
||||
|
||||
### flake8-bugbear
|
||||
|
||||
For more, see [flake8-bugbear](https://pypi.org/project/flake8-bugbear/22.10.27/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| B002 | UnaryPrefixIncrement | Python does not support the unary prefix increment. | |
|
||||
| B003 | AssignmentToOsEnviron | Assigning to `os.environ` doesn't clear the environment. | |
|
||||
| B002 | UnaryPrefixIncrement | Python does not support the unary prefix increment | |
|
||||
| B003 | AssignmentToOsEnviron | Assigning to `os.environ` doesn't clear the environment | |
|
||||
| B004 | UnreliableCallableCheck | Using `hasattr(x, '__call__')` to test if x is callable is unreliable. Use `callable(x)` for consistent results. | |
|
||||
| B005 | StripWithMultiCharacters | Using `.strip()` with multi-character strings is misleading the reader. | |
|
||||
| B006 | MutableArgumentDefault | Do not use mutable data structures for argument defaults. | |
|
||||
| B007 | UnusedLoopControlVariable | Loop control variable `i` not used within the loop body. | 🛠 |
|
||||
| B008 | FunctionCallArgumentDefault | Do not perform function calls in argument defaults. | |
|
||||
| B005 | StripWithMultiCharacters | Using `.strip()` with multi-character strings is misleading the reader | |
|
||||
| B006 | MutableArgumentDefault | Do not use mutable data structures for argument defaults | |
|
||||
| B007 | UnusedLoopControlVariable | Loop control variable `i` not used within the loop body | 🛠 |
|
||||
| B008 | FunctionCallArgumentDefault | Do not perform function call in argument defaults | |
|
||||
| B009 | GetAttrWithConstant | Do not call `getattr` with a constant attribute value. It is not any safer than normal property access. | 🛠 |
|
||||
| B010 | SetAttrWithConstant | Do not call `setattr` with a constant attribute value. It is not any safer than normal property access. | 🛠 |
|
||||
| B011 | DoNotAssertFalse | Do not `assert False` (`python -O` removes these calls), raise `AssertionError()` | 🛠 |
|
||||
| B013 | RedundantTupleInExceptionHandler | A length-one tuple literal is redundant. Write `except ValueError:` instead of `except (ValueError,):`. | |
|
||||
| B012 | JumpStatementInFinally | `return/continue/break` inside finally blocks cause exceptions to be silenced | |
|
||||
| B013 | RedundantTupleInExceptionHandler | A length-one tuple literal is redundant. Write `except ValueError` instead of `except (ValueError,)`. | 🛠 |
|
||||
| B014 | DuplicateHandlerException | Exception handler with duplicate exception: `ValueError` | 🛠 |
|
||||
| B015 | UselessComparison | Pointless comparison. This comparison does nothing but waste CPU instructions. Either prepend `assert` or remove it. | |
|
||||
| B016 | CannotRaiseLiteral | Cannot raise a literal. Did you intend to return it or raise an Exception? | |
|
||||
| B017 | NoAssertRaisesException | `assertRaises(Exception):` should be considered evil. | |
|
||||
| B017 | NoAssertRaisesException | `assertRaises(Exception)` should be considered evil | |
|
||||
| B018 | UselessExpression | Found useless expression. Either assign it to a variable or remove it. | |
|
||||
| B019 | CachedInstanceMethod | Use of `functools.lru_cache` or `functools.cache` on methods can lead to memory leaks | |
|
||||
| B020 | LoopVariableOverridesIterator | Loop control variable `...` overrides iterable it iterates | |
|
||||
| B021 | FStringDocstring | f-string used as docstring. This will be interpreted by python as a joined string rather than a docstring. | |
|
||||
| B022 | UselessContextlibSuppress | No arguments passed to `contextlib.suppress`. No exceptions will be suppressed and therefore this context manager is redundant | |
|
||||
| B024 | AbstractBaseClassWithoutAbstractMethod | `...` is an abstract base class, but it has no abstract methods | |
|
||||
| B025 | DuplicateTryBlockException | try-except block with duplicate exception `Exception` | |
|
||||
| B026 | StarArgUnpackingAfterKeywordArg | Star-arg unpacking after a keyword argument is strongly discouraged | |
|
||||
| B027 | EmptyMethodWithoutAbstractDecorator | `...` is an empty method in an abstract base class, but has no abstract decorator | |
|
||||
|
||||
### flake8-builtins
|
||||
|
||||
@@ -509,6 +585,14 @@ For more, see [flake8-builtins](https://pypi.org/project/flake8-builtins/2.0.1/)
|
||||
| A002 | BuiltinArgumentShadowing | Argument `...` is shadowing a python builtin | |
|
||||
| A003 | BuiltinAttributeShadowing | Class attribute `...` is shadowing a python builtin | |
|
||||
|
||||
### flake8-tidy-imports
|
||||
|
||||
For more, see [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/4.8.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| I252 | BannedRelativeImport | Relative imports are banned | |
|
||||
|
||||
### flake8-print
|
||||
|
||||
For more, see [flake8-print](https://pypi.org/project/flake8-print/5.0.0/) on PyPI.
|
||||
@@ -545,6 +629,40 @@ For more, see [flake8-annotations](https://pypi.org/project/flake8-annotations/2
|
||||
| ANN204 | MissingReturnTypeMagicMethod | Missing return type annotation for magic method `...` | |
|
||||
| ANN205 | MissingReturnTypeStaticMethod | Missing return type annotation for staticmethod `...` | |
|
||||
| ANN206 | MissingReturnTypeClassMethod | Missing return type annotation for classmethod `...` | |
|
||||
| ANN401 | DynamicallyTypedExpression | Dynamically typed expressions (typing.Any) are disallowed in `...` | |
|
||||
|
||||
### flake8-2020
|
||||
|
||||
For more, see [flake8-2020](https://pypi.org/project/flake8-2020/1.7.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| YTT101 | SysVersionSlice3Referenced | `sys.version[:3]` referenced (python3.10), use `sys.version_info` | |
|
||||
| YTT102 | SysVersion2Referenced | `sys.version[2]` referenced (python3.10), use `sys.version_info` | |
|
||||
| YTT103 | SysVersionCmpStr3 | `sys.version` compared to string (python3.10), use `sys.version_info` | |
|
||||
| YTT201 | SysVersionInfo0Eq3Referenced | `sys.version_info[0] == 3` referenced (python4), use `>=` | |
|
||||
| YTT202 | SixPY3Referenced | `six.PY3` referenced (python4), use `not six.PY2` | |
|
||||
| YTT203 | SysVersionInfo1CmpInt | `sys.version_info[1]` compared to integer (python4), compare `sys.version_info` to tuple | |
|
||||
| YTT204 | SysVersionInfoMinorCmpInt | `sys.version_info.minor` compared to integer (python4), compare `sys.version_info` to tuple | |
|
||||
| YTT301 | SysVersion0Referenced | `sys.version[0]` referenced (python10), use `sys.version_info` | |
|
||||
| YTT302 | SysVersionCmpStr10 | `sys.version` compared to string (python10), use `sys.version_info` | |
|
||||
| YTT303 | SysVersionSlice1Referenced | `sys.version[:1]` referenced (python10), use `sys.version_info` | |
|
||||
|
||||
### flake8-blind-except
|
||||
|
||||
For more, see [flake8-blind-except](https://pypi.org/project/flake8-blind-except/0.2.1/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| BLE001 | BlindExcept | Blind except Exception: statement | |
|
||||
|
||||
### mccabe
|
||||
|
||||
For more, see [mccabe](https://pypi.org/project/mccabe/0.7.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| C901 | FunctionIsTooComplex | `...` is too complex (10) | |
|
||||
|
||||
### Ruff-specific rules
|
||||
|
||||
@@ -552,6 +670,8 @@ For more, see [flake8-annotations](https://pypi.org/project/flake8-annotations/2
|
||||
| ---- | ---- | ------- | --- |
|
||||
| RUF001 | AmbiguousUnicodeCharacterString | String contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF002 | AmbiguousUnicodeCharacterDocstring | Docstring contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | |
|
||||
| RUF101 | ConvertExitToSysExit | `exit()` is only available in the interpreter, use `sys.exit()` instead | 🛠 |
|
||||
|
||||
### Meta rules
|
||||
|
||||
@@ -563,6 +683,10 @@ For more, see [flake8-annotations](https://pypi.org/project/flake8-annotations/2
|
||||
|
||||
## Editor Integrations
|
||||
|
||||
### VS Code (Official)
|
||||
|
||||
Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff).
|
||||
|
||||
### PyCharm
|
||||
|
||||
Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html)
|
||||
@@ -575,6 +699,70 @@ Ruff should then appear as a runnable action:
|
||||
|
||||

|
||||
|
||||
### Vim & Neovim (Unofficial)
|
||||
|
||||
Ruff is available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright) extension
|
||||
for coc.nvim.
|
||||
|
||||
<details>
|
||||
<summary>Ruff can also be integrated via <a href="https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#efm"><code>efm</code></a> in just a <a href="https://github.com/JafarAbdi/myconfigs/blob/6f0b6b2450e92ec8fc50422928cd22005b919110/efm-langserver/config.yaml#L14-L20">few lines</a>.</summary>
|
||||
<br>
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
python-ruff: &python-ruff
|
||||
lint-command: 'ruff --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}'
|
||||
lint-stdin: true
|
||||
lint-formats:
|
||||
- '%f:%l:%c: %m'
|
||||
format-command: 'ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -'
|
||||
format-stdin: true
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>For neovim users using <a href="https://github.com/jose-elias-alvarez/null-ls.nvim"><code>null-ls</code></a>, Ruff is already <a href="https://github.com/jose-elias-alvarez/null-ls.nvim">integrated</a>.</summary>
|
||||
<br>
|
||||
|
||||
```lua
|
||||
local null_ls = require("null-ls")
|
||||
local methods = require("null-ls.methods")
|
||||
local helpers = require("null-ls.helpers")
|
||||
|
||||
local function ruff_fix()
|
||||
return helpers.make_builtin({
|
||||
name = "ruff",
|
||||
meta = {
|
||||
url = "https://github.com/charliermarsh/ruff/",
|
||||
description = "An extremely fast Python linter, written in Rust.",
|
||||
},
|
||||
method = methods.internal.FORMATTING,
|
||||
filetypes = { "python" },
|
||||
generator_opts = {
|
||||
command = "ruff",
|
||||
args = { "--fix", "-e", "-n", "--stdin-filename", "$FILENAME", "-" },
|
||||
to_stdin = true
|
||||
},
|
||||
factory = helpers.formatter_factory
|
||||
})
|
||||
end
|
||||
|
||||
null_ls.setup({
|
||||
sources = {
|
||||
ruff_fix(),
|
||||
null_ls.builtins.diagnostics.ruff,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Language Server Protocol (Unofficial)
|
||||
|
||||
[`ruffd`](https://github.com/Seamooo/ruffd) is a Rust-based language server for Ruff that implements
|
||||
the Language Server Protocol (LSP).
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
GitHub Actions has everything you need to run Ruff out-of-the-box:
|
||||
@@ -629,12 +817,19 @@ including:
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-annotations`](https://pypi.org/project/flake8-annotations/)
|
||||
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (17/32)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (11/34)
|
||||
- [`flake8-bandit`](https://pypi.org/project/flake8-bandit/) (6/40)
|
||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (25/32)
|
||||
- [`flake8-2020`](https://pypi.org/project/flake8-2020/)
|
||||
- [`flake8-blind-except`](https://pypi.org/project/flake8-blind-except/)
|
||||
- [`flake8-boolean-trap`](https://pypi.org/project/flake8-boolean-trap/)
|
||||
- [`mccabe`](https://pypi.org/project/mccabe/)
|
||||
- [`isort`](https://pypi.org/project/isort/)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (16/33)
|
||||
- [`autoflake`](https://pypi.org/project/autoflake/) (1/7)
|
||||
|
||||
Beyond rule-set parity, Ruff suffers from the following limitations vis-à-vis Flake8:
|
||||
@@ -648,18 +843,25 @@ Beyond rule-set parity, Ruff suffers from the following limitations vis-à-vis F
|
||||
|
||||
Today, Ruff can be used to replace Flake8 when used with any of the following plugins:
|
||||
|
||||
- [`pydocstyle`](https://pypi.org/project/pydocstyle/)
|
||||
- [`pep8-naming`](https://pypi.org/project/pep8-naming/)
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-annotations`](https://pypi.org/project/flake8-annotations/)
|
||||
- [`flake8-bandit`](https://pypi.org/project/flake8-bandit/) (6/40)
|
||||
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (17/32)
|
||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (26/32)
|
||||
- [`flake8-2020`](https://pypi.org/project/flake8-2020/)
|
||||
- [`flake8-blind-except`](https://pypi.org/project/flake8-blind-except/)
|
||||
- [`flake8-boolean-trap`](https://pypi.org/project/flake8-boolean-trap/)
|
||||
- [`mccabe`](https://pypi.org/project/mccabe/)
|
||||
|
||||
Ruff also implements the functionality that you get from [`yesqa`](https://github.com/asottile/yesqa),
|
||||
and a subset of the rules implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (11/34).
|
||||
Ruff can also replace [`isort`](https://pypi.org/project/isort/), [`yesqa`](https://github.com/asottile/yesqa),
|
||||
and a subset of the rules implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (16/33).
|
||||
|
||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, free to file an Issue.
|
||||
|
||||
@@ -679,6 +881,33 @@ on Rust at all.
|
||||
Ruff does not yet support third-party plugins, though a plugin system is within-scope for the
|
||||
project. See [#283](https://github.com/charliermarsh/ruff/issues/283) for more.
|
||||
|
||||
### How does Ruff's import sorting compare to [`isort`](https://pypi.org/project/isort/)?
|
||||
|
||||
Ruff's import sorting is intended to be nearly equivalent to `isort` when used `profile = "black"`.
|
||||
(There are some minor differences in how Ruff and isort break ties between similar imports.)
|
||||
|
||||
Like `isort`, Ruff's import sorting is compatible with Black.
|
||||
|
||||
Ruff is less configurable than `isort`, but supports the `known-first-party`, `known-third-party`,
|
||||
`extra-standard-library`, and `src` settings, like so:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
select = [
|
||||
# Pyflakes
|
||||
"F",
|
||||
# Pycodestyle
|
||||
"E",
|
||||
"W",
|
||||
# isort
|
||||
"I001"
|
||||
]
|
||||
src = ["src", "tests"]
|
||||
|
||||
[tool.ruff.isort]
|
||||
known-first-party = ["my_module1", "my_module2"]
|
||||
```
|
||||
|
||||
### Does Ruff support NumPy- or Google-style docstrings?
|
||||
|
||||
Yes! To enable a specific docstring convention, start by enabling all `pydocstyle` error codes, and
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use ropey::Rope;
|
||||
use ruff::fs;
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
let contents = fs::read_file(Path::new("resources/test/fixtures/D.py")).unwrap();
|
||||
let contents = fs::read_to_string(Path::new("resources/test/fixtures/D.py")).unwrap();
|
||||
c.bench_function("rope", |b| {
|
||||
b.iter(|| {
|
||||
let rope = Rope::from_str(black_box(&contents));
|
||||
rope.line_to_char(black_box(4));
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
18
flake8_to_ruff/Cargo.lock
generated
18
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.106"
|
||||
version = "0.0.136"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1265,7 +1265,7 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
[[package]]
|
||||
name = "libcst"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=32a044c127668df44582f85699358e67803b0d73#32a044c127668df44582f85699358e67803b0d73"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=a13ec97dd4eb925bde4d426c6e422582793b260c#a13ec97dd4eb925bde4d426c6e422582793b260c"
|
||||
dependencies = [
|
||||
"chic",
|
||||
"itertools",
|
||||
@@ -1280,7 +1280,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libcst_derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=32a044c127668df44582f85699358e67803b0d73#32a044c127668df44582f85699358e67803b0d73"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=a13ec97dd4eb925bde4d426c6e422582793b260c#a13ec97dd4eb925bde4d426c6e422582793b260c"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -1505,7 +1505,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.106"
|
||||
version = "0.0.136"
|
||||
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=77b821a1941019fe34f73ce17cea013ae1b98fd0#77b821a1941019fe34f73ce17cea013ae1b98fd0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
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=77b821a1941019fe34f73ce17cea013ae1b98fd0#77b821a1941019fe34f73ce17cea013ae1b98fd0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
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=77b821a1941019fe34f73ce17cea013ae1b98fd0#77b821a1941019fe34f73ce17cea013ae1b98fd0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
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=77b821a1941019fe34f73ce17cea013ae1b98fd0#77b821a1941019fe34f73ce17cea013ae1b98fd0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.106-dev.0"
|
||||
version = "0.0.136-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "flake8_to_ruff"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.60" }
|
||||
anyhow = { version = "1.0.66" }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
configparser = { version = "3.0.2" }
|
||||
once_cell = { version = "1.13.1" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
regex = { version = "1.6.0" }
|
||||
ruff = { path = "..", default-features = false }
|
||||
serde = { version = "1.0.143", features = ["derive"] }
|
||||
serde_json = { version = "1.0.83" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
toml = { version = "0.5.9" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -25,7 +25,7 @@ requires-python = ">=3.7"
|
||||
repository = "https://github.com/charliermarsh/ruff#subdirectory=crates/flake8_to_ruff"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin>=0.13,<0.14"]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[tool.maturin]
|
||||
|
||||
@@ -3,9 +3,12 @@ use std::collections::{BTreeSet, HashMap};
|
||||
use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::flake8_quotes::settings::Quote;
|
||||
use ruff::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{flake8_annotations, flake8_quotes, pep8_naming};
|
||||
use ruff::{
|
||||
flake8_annotations, flake8_bugbear, flake8_quotes, flake8_tidy_imports, mccabe, pep8_naming,
|
||||
};
|
||||
|
||||
use crate::plugin::Plugin;
|
||||
use crate::{parser, plugin};
|
||||
@@ -15,7 +18,7 @@ pub fn convert(
|
||||
plugins: Option<Vec<Plugin>>,
|
||||
) -> Result<Pyproject> {
|
||||
// Extract all referenced check code prefixes, to power plugin inference.
|
||||
let mut referenced_codes: BTreeSet<CheckCodePrefix> = Default::default();
|
||||
let mut referenced_codes: BTreeSet<CheckCodePrefix> = BTreeSet::default();
|
||||
for (key, value) in flake8 {
|
||||
if let Some(value) = value {
|
||||
match key.as_str() {
|
||||
@@ -67,10 +70,13 @@ pub fn convert(
|
||||
.unwrap_or_default();
|
||||
|
||||
// Parse each supported option.
|
||||
let mut options: Options = Default::default();
|
||||
let mut flake8_annotations: flake8_annotations::settings::Options = Default::default();
|
||||
let mut flake8_quotes: flake8_quotes::settings::Options = Default::default();
|
||||
let mut pep8_naming: pep8_naming::settings::Options = Default::default();
|
||||
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_quotes = flake8_quotes::settings::Options::default();
|
||||
let mut flake8_tidy_imports = flake8_tidy_imports::settings::Options::default();
|
||||
let mut mccabe = mccabe::settings::Options::default();
|
||||
let mut pep8_naming = pep8_naming::settings::Options::default();
|
||||
for (key, value) in flake8 {
|
||||
if let Some(value) = value {
|
||||
match key.as_str() {
|
||||
@@ -104,11 +110,16 @@ pub fn convert(
|
||||
match parser::parse_files_to_codes_mapping(value.as_ref()) {
|
||||
Ok(per_file_ignores) => {
|
||||
options.per_file_ignores =
|
||||
Some(parser::collect_per_file_ignores(per_file_ignores))
|
||||
Some(parser::collect_per_file_ignores(per_file_ignores));
|
||||
}
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
// flake8-bugbear
|
||||
"extend-immutable-calls" | "extend_immutable_calls" => {
|
||||
flake8_bugbear.extend_immutable_calls =
|
||||
Some(parser::parse_strings(value.as_ref()));
|
||||
}
|
||||
// flake8-annotations
|
||||
"suppress-none-returning" | "suppress_none_returning" => {
|
||||
match parser::parse_bool(value.as_ref()) {
|
||||
@@ -128,6 +139,12 @@ pub fn convert(
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
"allow-star-arg-any" | "allow_star_arg_any" => {
|
||||
match parser::parse_bool(value.as_ref()) {
|
||||
Ok(bool) => flake8_annotations.allow_star_arg_any = Some(bool),
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
// flake8-quotes
|
||||
"quotes" | "inline-quotes" | "inline_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.inline_quotes = Some(Quote::Single),
|
||||
@@ -160,10 +177,23 @@ pub fn convert(
|
||||
pep8_naming.staticmethod_decorators =
|
||||
Some(parser::parse_strings(value.as_ref()));
|
||||
}
|
||||
// flake8-tidy-imports
|
||||
"ban-relative-imports" | "ban_relative_imports" => match value.trim() {
|
||||
"true" => flake8_tidy_imports.ban_relative_imports = Some(Strictness::All),
|
||||
"parents" => {
|
||||
flake8_tidy_imports.ban_relative_imports = Some(Strictness::Parents);
|
||||
}
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
// flake8-docstrings
|
||||
"docstring-convention" => {
|
||||
// No-op (handled above).
|
||||
}
|
||||
// mccabe
|
||||
"max-complexity" | "max_complexity" => match value.clone().parse::<usize>() {
|
||||
Ok(max_complexity) => mccabe.max_complexity = Some(max_complexity),
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
},
|
||||
// Unknown
|
||||
_ => eprintln!("Skipping unsupported property: {key}"),
|
||||
}
|
||||
@@ -173,10 +203,22 @@ pub fn convert(
|
||||
// Deduplicate and sort.
|
||||
options.select = Some(Vec::from_iter(select));
|
||||
options.ignore = Some(Vec::from_iter(ignore));
|
||||
if flake8_quotes != Default::default() {
|
||||
if flake8_annotations != flake8_annotations::settings::Options::default() {
|
||||
options.flake8_annotations = Some(flake8_annotations);
|
||||
}
|
||||
if flake8_bugbear != flake8_bugbear::settings::Options::default() {
|
||||
options.flake8_bugbear = Some(flake8_bugbear);
|
||||
}
|
||||
if flake8_quotes != flake8_quotes::settings::Options::default() {
|
||||
options.flake8_quotes = Some(flake8_quotes);
|
||||
}
|
||||
if pep8_naming != Default::default() {
|
||||
if flake8_tidy_imports != flake8_tidy_imports::settings::Options::default() {
|
||||
options.flake8_tidy_imports = Some(flake8_tidy_imports);
|
||||
}
|
||||
if mccabe != mccabe::settings::Options::default() {
|
||||
options.mccabe = Some(mccabe);
|
||||
}
|
||||
if pep8_naming != pep8_naming::settings::Options::default() {
|
||||
options.pep8_naming = Some(pep8_naming);
|
||||
}
|
||||
|
||||
@@ -201,22 +243,31 @@ mod tests {
|
||||
fn it_converts_empty() -> Result<()> {
|
||||
let actual = convert(&HashMap::from([]), None)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -231,22 +282,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(100),
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -261,22 +321,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(100),
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -291,22 +360,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -321,27 +399,36 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -359,9 +446,16 @@ mod tests {
|
||||
Some(vec![Plugin::Flake8Docstrings]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
@@ -402,14 +496,16 @@ mod tests {
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -424,28 +520,37 @@ mod tests {
|
||||
None,
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend_exclude: None,
|
||||
extend_ignore: None,
|
||||
extend_select: None,
|
||||
fix: None,
|
||||
fixable: None,
|
||||
ignore: Some(vec![]),
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::Q,
|
||||
CheckCodePrefix::W,
|
||||
]),
|
||||
extend_select: None,
|
||||
ignore: Some(vec![]),
|
||||
extend_ignore: None,
|
||||
per_file_ignores: None,
|
||||
dummy_variable_rgx: None,
|
||||
show_source: None,
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
clippy::collapsible_if,
|
||||
clippy::implicit_hasher,
|
||||
clippy::match_same_arms,
|
||||
clippy::missing_errors_doc,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::similar_names,
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
pub mod converter;
|
||||
mod parser;
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
//! Utility to generate Ruff's pyproject.toml section from a Flake8 INI file.
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
clippy::collapsible_if,
|
||||
clippy::implicit_hasher,
|
||||
clippy::match_same_arms,
|
||||
clippy::missing_errors_doc,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::similar_names,
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
@@ -6,6 +5,7 @@ use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
static COMMA_SEPARATED_LIST_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[,\s]").unwrap());
|
||||
|
||||
@@ -31,7 +31,7 @@ pub fn parse_prefix_codes(value: &str) -> Vec<CheckCodePrefix> {
|
||||
pub fn parse_strings(value: &str) -> Vec<String> {
|
||||
COMMA_SEPARATED_LIST_RE
|
||||
.split(value)
|
||||
.map(|part| part.trim())
|
||||
.map(str::trim)
|
||||
.filter(|part| !part.is_empty())
|
||||
.map(String::from)
|
||||
.collect()
|
||||
@@ -92,7 +92,7 @@ impl State {
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(_) => eprintln!("Skipping unrecognized prefix: {}", code),
|
||||
Err(_) => eprintln!("Skipping unrecognized prefix: {code}"),
|
||||
}
|
||||
}
|
||||
codes
|
||||
@@ -129,14 +129,14 @@ fn tokenize_files_to_codes_mapping(value: &str) -> Vec<Token> {
|
||||
}
|
||||
tokens.push(Token {
|
||||
token_name: TokenType::Eof,
|
||||
src: "".to_string(),
|
||||
src: String::new(),
|
||||
});
|
||||
tokens
|
||||
}
|
||||
|
||||
/// Parse a 'files-to-codes' mapping, mimicking Flake8's internal logic.
|
||||
///
|
||||
/// See: https://github.com/PyCQA/flake8/blob/7dfe99616fc2f07c0017df2ba5fa884158f3ea8a/src/flake8/utils.py#L45
|
||||
/// 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() {
|
||||
return Ok(vec![]);
|
||||
@@ -179,8 +179,8 @@ pub fn parse_files_to_codes_mapping(value: &str) -> Result<Vec<PatternPrefixPair
|
||||
/// Collect a list of `PatternPrefixPair` structs as a `BTreeMap`.
|
||||
pub fn collect_per_file_ignores(
|
||||
pairs: Vec<PatternPrefixPair>,
|
||||
) -> BTreeMap<String, Vec<CheckCodePrefix>> {
|
||||
let mut per_file_ignores: BTreeMap<String, Vec<CheckCodePrefix>> = BTreeMap::new();
|
||||
) -> FxHashMap<String, Vec<CheckCodePrefix>> {
|
||||
let mut per_file_ignores: FxHashMap<String, Vec<CheckCodePrefix>> = FxHashMap::default();
|
||||
for pair in pairs {
|
||||
per_file_ignores
|
||||
.entry(pair.pattern)
|
||||
|
||||
@@ -6,13 +6,17 @@ use ruff::checks_gen::CheckCodePrefix;
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Plugin {
|
||||
Flake8Bandit,
|
||||
Flake8Bugbear,
|
||||
Flake8Builtins,
|
||||
Flake8Comprehensions,
|
||||
Flake8Docstrings,
|
||||
Flake8TidyImports,
|
||||
Flake8Print,
|
||||
Flake8Quotes,
|
||||
Flake8Annotations,
|
||||
McCabe,
|
||||
Flake8BlindExcept,
|
||||
PEP8Naming,
|
||||
Pyupgrade,
|
||||
}
|
||||
@@ -22,13 +26,17 @@ impl FromStr for Plugin {
|
||||
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
match string {
|
||||
"flake8-bandit" => Ok(Plugin::Flake8Bandit),
|
||||
"flake8-bugbear" => Ok(Plugin::Flake8Bugbear),
|
||||
"flake8-builtins" => Ok(Plugin::Flake8Builtins),
|
||||
"flake8-comprehensions" => Ok(Plugin::Flake8Comprehensions),
|
||||
"flake8-docstrings" => Ok(Plugin::Flake8Docstrings),
|
||||
"flake8-tidy-imports" => Ok(Plugin::Flake8TidyImports),
|
||||
"flake8-print" => Ok(Plugin::Flake8Print),
|
||||
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
|
||||
"flake8-annotations" => Ok(Plugin::Flake8Annotations),
|
||||
"flake8-blind-except" => Ok(Plugin::Flake8BlindExcept),
|
||||
"mccabe" => Ok(Plugin::McCabe),
|
||||
"pep8-naming" => Ok(Plugin::PEP8Naming),
|
||||
"pyupgrade" => Ok(Plugin::Pyupgrade),
|
||||
_ => Err(anyhow!("Unknown plugin: {}", string)),
|
||||
@@ -39,13 +47,17 @@ impl FromStr for Plugin {
|
||||
impl Plugin {
|
||||
pub fn default(&self) -> CheckCodePrefix {
|
||||
match self {
|
||||
Plugin::Flake8Bandit => CheckCodePrefix::S,
|
||||
Plugin::Flake8Bugbear => CheckCodePrefix::B,
|
||||
Plugin::Flake8Builtins => CheckCodePrefix::A,
|
||||
Plugin::Flake8Comprehensions => CheckCodePrefix::C,
|
||||
Plugin::Flake8Comprehensions => CheckCodePrefix::C4,
|
||||
Plugin::Flake8Docstrings => CheckCodePrefix::D,
|
||||
Plugin::Flake8TidyImports => CheckCodePrefix::I25,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T,
|
||||
Plugin::Flake8Quotes => CheckCodePrefix::Q,
|
||||
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
|
||||
Plugin::Flake8BlindExcept => CheckCodePrefix::BLE,
|
||||
Plugin::McCabe => CheckCodePrefix::C9,
|
||||
Plugin::PEP8Naming => CheckCodePrefix::N,
|
||||
Plugin::Pyupgrade => CheckCodePrefix::U,
|
||||
}
|
||||
@@ -53,9 +65,10 @@ impl Plugin {
|
||||
|
||||
pub fn select(&self, flake8: &HashMap<String, Option<String>>) -> Vec<CheckCodePrefix> {
|
||||
match self {
|
||||
Plugin::Flake8Bandit => vec![CheckCodePrefix::S],
|
||||
Plugin::Flake8Bugbear => vec![CheckCodePrefix::B],
|
||||
Plugin::Flake8Builtins => vec![CheckCodePrefix::A],
|
||||
Plugin::Flake8Comprehensions => vec![CheckCodePrefix::C],
|
||||
Plugin::Flake8Comprehensions => vec![CheckCodePrefix::C4],
|
||||
Plugin::Flake8Docstrings => {
|
||||
// Use the user-provided docstring.
|
||||
for key in ["docstring-convention", "docstring_convention"] {
|
||||
@@ -72,9 +85,12 @@ impl Plugin {
|
||||
// Default to PEP8.
|
||||
DocstringConvention::PEP8.select()
|
||||
}
|
||||
Plugin::Flake8TidyImports => vec![CheckCodePrefix::I25],
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T],
|
||||
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
|
||||
Plugin::Flake8Annotations => vec![CheckCodePrefix::ANN],
|
||||
Plugin::Flake8BlindExcept => vec![CheckCodePrefix::BLE],
|
||||
Plugin::McCabe => vec![CheckCodePrefix::C9],
|
||||
Plugin::PEP8Naming => vec![CheckCodePrefix::N],
|
||||
Plugin::Pyupgrade => vec![CheckCodePrefix::U],
|
||||
}
|
||||
@@ -265,6 +281,10 @@ pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> V
|
||||
"docstring-convention" | "docstring_convention" => {
|
||||
plugins.insert(Plugin::Flake8Docstrings);
|
||||
}
|
||||
// flake8-bugbear
|
||||
"extend-immutable-calls" | "extend_immutable_calls" => {
|
||||
plugins.insert(Plugin::Flake8Bugbear);
|
||||
}
|
||||
// flake8-builtins
|
||||
"builtins-ignorelist" | "builtins_ignorelist" => {
|
||||
plugins.insert(Plugin::Flake8Builtins);
|
||||
@@ -307,6 +327,17 @@ pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> V
|
||||
"allow-star-arg-any" | "allow_star_arg_any" => {
|
||||
plugins.insert(Plugin::Flake8Annotations);
|
||||
}
|
||||
// flake8-tidy-imports
|
||||
"ban-relative-imports" | "ban_relative_imports" => {
|
||||
plugins.insert(Plugin::Flake8TidyImports);
|
||||
}
|
||||
"banned-modules" | "banned_modules" => {
|
||||
plugins.insert(Plugin::Flake8TidyImports);
|
||||
}
|
||||
// mccabe
|
||||
"max-complexity" | "max_complexity" => {
|
||||
plugins.insert(Plugin::McCabe);
|
||||
}
|
||||
// pep8-naming
|
||||
"ignore-names" | "ignore_names" => {
|
||||
plugins.insert(Plugin::PEP8Naming);
|
||||
@@ -329,13 +360,16 @@ pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> V
|
||||
/// `flake8-annotations` is active.
|
||||
pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin> {
|
||||
[
|
||||
Plugin::Flake8Bandit,
|
||||
Plugin::Flake8Bugbear,
|
||||
Plugin::Flake8Builtins,
|
||||
Plugin::Flake8Comprehensions,
|
||||
Plugin::Flake8Docstrings,
|
||||
Plugin::Flake8TidyImports,
|
||||
Plugin::Flake8Print,
|
||||
Plugin::Flake8Quotes,
|
||||
Plugin::Flake8Annotations,
|
||||
Plugin::Flake8BlindExcept,
|
||||
Plugin::PEP8Naming,
|
||||
Plugin::Pyupgrade,
|
||||
]
|
||||
|
||||
@@ -25,10 +25,13 @@ requires-python = ">=3.7"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin>=0.13,<0.14"]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[tool.maturin]
|
||||
bindings = "bin"
|
||||
sdist-include = ["Cargo.lock"]
|
||||
strip = true
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
known_third_party = ["fastapi", "pydantic", "starlette"]
|
||||
|
||||
20
resources/test/fixtures/B006_B008.py
vendored
20
resources/test/fixtures/B006_B008.py
vendored
@@ -185,3 +185,23 @@ def nested_b008(a=random.randint(0, dt.datetime.now().year)):
|
||||
# Ignore lambda contents since they are evaluated at call time.
|
||||
def foo(f=lambda x: print(x)):
|
||||
f(1)
|
||||
|
||||
|
||||
from collections import abc
|
||||
from typing import Annotated, Dict, Optional, Sequence, Union, Set
|
||||
|
||||
|
||||
def immutable_annotations(
|
||||
a: Sequence[int] | None = [],
|
||||
b: Optional[abc.Mapping[int, int]] = {},
|
||||
c: Annotated[Union[abc.Set[str], abc.Sized], "annotation"] = set(),
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def mutable_annotations(
|
||||
a: list[int] | None = [],
|
||||
b: Optional[Dict[int, int]] = {},
|
||||
c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
):
|
||||
pass
|
||||
|
||||
20
resources/test/fixtures/B008_extended.py
vendored
Normal file
20
resources/test/fixtures/B008_extended.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
from typing import List
|
||||
|
||||
import fastapi
|
||||
from fastapi import Query
|
||||
|
||||
|
||||
def okay(db=fastapi.Depends(get_db)):
|
||||
...
|
||||
|
||||
|
||||
def okay(data: List[str] = fastapi.Query(None)):
|
||||
...
|
||||
|
||||
|
||||
def okay(data: List[str] = Query(None)):
|
||||
...
|
||||
|
||||
|
||||
def error_due_to_missing_import(data: List[str] = Depends(None)):
|
||||
...
|
||||
37
resources/test/fixtures/B009_B010.py
vendored
Normal file
37
resources/test/fixtures/B009_B010.py
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Should emit:
|
||||
B009 - Line 18, 19, 20, 21, 22
|
||||
B010 - Line 33, 34, 35, 36
|
||||
"""
|
||||
|
||||
# Valid getattr usage
|
||||
getattr(foo, bar)
|
||||
getattr(foo, "bar", None)
|
||||
getattr(foo, "bar{foo}".format(foo="a"), None)
|
||||
getattr(foo, "bar{foo}".format(foo="a"))
|
||||
getattr(foo, bar, None)
|
||||
getattr(foo, "123abc")
|
||||
getattr(foo, r"123\abc")
|
||||
getattr(foo, "except")
|
||||
|
||||
# Invalid usage
|
||||
getattr(foo, "bar")
|
||||
getattr(foo, "_123abc")
|
||||
getattr(foo, "abc123")
|
||||
getattr(foo, r"abc123")
|
||||
_ = lambda x: getattr(x, "bar")
|
||||
|
||||
# Valid setattr usage
|
||||
setattr(foo, bar, None)
|
||||
setattr(foo, "bar{foo}".format(foo="a"), None)
|
||||
setattr(foo, "123abc", None)
|
||||
setattr(foo, r"123\abc", None)
|
||||
setattr(foo, "except", None)
|
||||
_ = lambda x: setattr(x, "bar", 1)
|
||||
|
||||
# Invalid usage
|
||||
setattr(foo, "bar", None)
|
||||
setattr(foo, "_123abc", None)
|
||||
setattr(foo, "abc123", None)
|
||||
setattr(foo, r"abc123", None)
|
||||
setattr(foo.bar, r"baz", None)
|
||||
107
resources/test/fixtures/B012.py
vendored
Normal file
107
resources/test/fixtures/B012.py
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
def a():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
return # warning
|
||||
|
||||
|
||||
def b():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
if 1 + 0 == 2 - 1:
|
||||
return # warning
|
||||
|
||||
|
||||
def c():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
return # warning
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def d():
|
||||
try:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
return # warning
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
def e():
|
||||
if 1 == 2 - 1:
|
||||
try:
|
||||
|
||||
def f():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
return # warning
|
||||
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
def g():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
|
||||
def h():
|
||||
return # no warning
|
||||
|
||||
e()
|
||||
|
||||
|
||||
def i():
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
break # warning
|
||||
|
||||
def j():
|
||||
while True:
|
||||
break # no warning
|
||||
|
||||
|
||||
def h():
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # warning
|
||||
|
||||
def j():
|
||||
while True:
|
||||
continue # no warning
|
||||
|
||||
|
||||
def k():
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
while True:
|
||||
break # no warning
|
||||
while True:
|
||||
continue # no warning
|
||||
while True:
|
||||
return # warning
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # warning
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
break # warning
|
||||
108
resources/test/fixtures/B019.py
vendored
Normal file
108
resources/test/fixtures/B019.py
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
Should emit:
|
||||
B019 - on lines 73, 77, 81, 85, 89, 93, 97, 101
|
||||
"""
|
||||
import functools
|
||||
from functools import cache, cached_property, lru_cache
|
||||
|
||||
|
||||
def some_other_cache():
|
||||
...
|
||||
|
||||
|
||||
@functools.cache
|
||||
def compute_func(self, y):
|
||||
...
|
||||
|
||||
|
||||
class Foo:
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
|
||||
def compute_method(self, y):
|
||||
...
|
||||
|
||||
@some_other_cache
|
||||
def user_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@functools.cache
|
||||
def cached_classmethod(cls, y):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@cache
|
||||
def other_cached_classmethod(cls, y):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@functools.lru_cache
|
||||
def lru_cached_classmethod(cls, y):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@lru_cache
|
||||
def other_lru_cached_classmethod(cls, y):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@functools.cache
|
||||
def cached_staticmethod(y):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@cache
|
||||
def other_cached_staticmethod(y):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@functools.lru_cache
|
||||
def lru_cached_staticmethod(y):
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@lru_cache
|
||||
def other_lru_cached_staticmethod(y):
|
||||
...
|
||||
|
||||
@functools.cached_property
|
||||
def some_cached_property(self):
|
||||
...
|
||||
|
||||
@cached_property
|
||||
def some_other_cached_property(self):
|
||||
...
|
||||
|
||||
# Remaining methods should emit B019
|
||||
@functools.cache
|
||||
def cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@cache
|
||||
def another_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@functools.cache()
|
||||
def called_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@cache()
|
||||
def another_called_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@functools.lru_cache
|
||||
def lru_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@lru_cache
|
||||
def another_lru_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@functools.lru_cache()
|
||||
def called_lru_cached_instance_method(self, y):
|
||||
...
|
||||
|
||||
@lru_cache()
|
||||
def another_called_lru_cached_instance_method(self, y):
|
||||
...
|
||||
40
resources/test/fixtures/B020.py
vendored
Normal file
40
resources/test/fixtures/B020.py
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
Should emit:
|
||||
B020 - on lines 8, 21, and 36
|
||||
"""
|
||||
|
||||
items = [1, 2, 3]
|
||||
|
||||
for items in items:
|
||||
print(items)
|
||||
|
||||
items = [1, 2, 3]
|
||||
|
||||
for item in items:
|
||||
print(item)
|
||||
|
||||
values = {"secret": 123}
|
||||
|
||||
for key, value in values.items():
|
||||
print(f"{key}, {value}")
|
||||
|
||||
for key, values in values.items():
|
||||
print(f"{key}, {values}")
|
||||
|
||||
# Variables defined in a comprehension are local in scope
|
||||
# to that comprehension and are therefore allowed.
|
||||
for var in [var for var in range(10)]:
|
||||
print(var)
|
||||
|
||||
for var in (var for var in range(10)):
|
||||
print(var)
|
||||
|
||||
for k, v in {k: v for k, v in zip(range(10), range(10, 20))}.items():
|
||||
print(k, v)
|
||||
|
||||
# However we still call out reassigning the iterable in the comprehension.
|
||||
for vars in [i for i in vars]:
|
||||
print(vars)
|
||||
|
||||
for var in sorted(range(10), key=lambda var: var.real):
|
||||
print(var)
|
||||
76
resources/test/fixtures/B021.py
vendored
Normal file
76
resources/test/fixtures/B021.py
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
f"""
|
||||
Should emit:
|
||||
B021 - on lines 14, 22, 30, 38, 46, 54, 62, 70, 73
|
||||
"""
|
||||
|
||||
VARIABLE = "world"
|
||||
|
||||
|
||||
def foo1():
|
||||
"""hello world!"""
|
||||
|
||||
|
||||
def foo2():
|
||||
f"""hello {VARIABLE}!"""
|
||||
|
||||
|
||||
class bar1:
|
||||
"""hello world!"""
|
||||
|
||||
|
||||
class bar2:
|
||||
f"""hello {VARIABLE}!"""
|
||||
|
||||
|
||||
def foo1():
|
||||
"""hello world!"""
|
||||
|
||||
|
||||
def foo2():
|
||||
f"""hello {VARIABLE}!"""
|
||||
|
||||
|
||||
class bar1:
|
||||
"""hello world!"""
|
||||
|
||||
|
||||
class bar2:
|
||||
f"""hello {VARIABLE}!"""
|
||||
|
||||
|
||||
def foo1():
|
||||
"hello world!"
|
||||
|
||||
|
||||
def foo2():
|
||||
f"hello {VARIABLE}!"
|
||||
|
||||
|
||||
class bar1:
|
||||
"hello world!"
|
||||
|
||||
|
||||
class bar2:
|
||||
f"hello {VARIABLE}!"
|
||||
|
||||
|
||||
def foo1():
|
||||
"hello world!"
|
||||
|
||||
|
||||
def foo2():
|
||||
f"hello {VARIABLE}!"
|
||||
|
||||
|
||||
class bar1:
|
||||
"hello world!"
|
||||
|
||||
|
||||
class bar2:
|
||||
f"hello {VARIABLE}!"
|
||||
|
||||
|
||||
def baz():
|
||||
f"""I'm probably a docstring: {VARIABLE}!"""
|
||||
print(f"""I'm a normal string""")
|
||||
f"""Don't detect me!"""
|
||||
23
resources/test/fixtures/B022.py
vendored
Normal file
23
resources/test/fixtures/B022.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Should emit:
|
||||
B022 - on lines 8
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
from contextlib import suppress
|
||||
|
||||
with contextlib.suppress():
|
||||
raise ValueError
|
||||
|
||||
with suppress():
|
||||
raise ValueError
|
||||
|
||||
with contextlib.suppress(ValueError):
|
||||
raise ValueError
|
||||
|
||||
exceptions_to_suppress = []
|
||||
if True:
|
||||
exceptions_to_suppress.append(ValueError)
|
||||
|
||||
with contextlib.suppress(*exceptions_to_suppress):
|
||||
raise
|
||||
129
resources/test/fixtures/B024.py
vendored
Normal file
129
resources/test/fixtures/B024.py
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
"""
|
||||
Should emit:
|
||||
B024 - on lines 17, 34, 52, 58, 69, 74, 79, 84, 89
|
||||
"""
|
||||
|
||||
import abc
|
||||
import abc as notabc
|
||||
from abc import ABC, ABCMeta
|
||||
from abc import abstractmethod
|
||||
from abc import abstractmethod as abstract
|
||||
from abc import abstractmethod as abstractaoeuaoeuaoeu
|
||||
from abc import abstractmethod as notabstract
|
||||
|
||||
import foo
|
||||
|
||||
|
||||
class Base_1(ABC): # error
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_2(ABC):
|
||||
@abstractmethod
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_3(ABC):
|
||||
@abc.abstractmethod
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_4(ABC):
|
||||
@notabc.abstractmethod
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_5(ABC):
|
||||
@abstract
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_6(ABC):
|
||||
@abstractaoeuaoeuaoeu
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class Base_7(ABC): # error
|
||||
@notabstract
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class MetaBase_1(metaclass=ABCMeta): # error
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class MetaBase_2(metaclass=ABCMeta):
|
||||
@abstractmethod
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class abc_Base_1(abc.ABC): # error
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class abc_Base_2(metaclass=abc.ABCMeta): # error
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class notabc_Base_1(notabc.ABC): # error
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class multi_super_1(notabc.ABC, abc.ABCMeta): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class multi_super_2(notabc.ABC, metaclass=abc.ABCMeta): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class non_keyword_abcmeta_1(ABCMeta): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class non_keyword_abcmeta_2(abc.ABCMeta): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
# very invalid code, but that's up to mypy et al to check
|
||||
class keyword_abc_1(metaclass=ABC): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class keyword_abc_2(metaclass=abc.ABC): # safe
|
||||
def method(self):
|
||||
foo()
|
||||
|
||||
|
||||
class abc_set_class_variable_1(ABC): # safe
|
||||
foo: int
|
||||
|
||||
|
||||
class abc_set_class_variable_2(ABC): # safe
|
||||
foo = 2
|
||||
|
||||
|
||||
class abc_set_class_variable_3(ABC): # safe
|
||||
foo: int = 2
|
||||
|
||||
|
||||
# this doesn't actually declare a class variable, it's just an expression
|
||||
class abc_set_class_variable_4(ABC): # error
|
||||
foo
|
||||
21
resources/test/fixtures/B026.py
vendored
Normal file
21
resources/test/fixtures/B026.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Should emit:
|
||||
B026 - on lines 16, 17, 18, 19, 20, 21
|
||||
"""
|
||||
|
||||
|
||||
def foo(bar, baz, bam):
|
||||
print(bar, baz, bam)
|
||||
|
||||
|
||||
bar_baz = ["bar", "baz"]
|
||||
|
||||
foo("bar", "baz", bam="bam")
|
||||
foo("bar", baz="baz", bam="bam")
|
||||
foo(bar="bar", baz="baz", bam="bam")
|
||||
foo(bam="bam", *["bar", "baz"])
|
||||
foo(bam="bam", *bar_baz)
|
||||
foo(baz="baz", bam="bam", *["bar"])
|
||||
foo(bar="bar", baz="baz", bam="bam", *[])
|
||||
foo(bam="bam", *["bar"], *["baz"])
|
||||
foo(*["bar"], bam="bam", *["baz"])
|
||||
88
resources/test/fixtures/B027.py
vendored
Normal file
88
resources/test/fixtures/B027.py
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
"""
|
||||
Should emit:
|
||||
B027 - on lines 12, 15, 18, 22, 30
|
||||
"""
|
||||
import abc
|
||||
from abc import ABC
|
||||
from abc import abstractmethod
|
||||
from abc import abstractmethod as notabstract
|
||||
|
||||
|
||||
class AbstractClass(ABC):
|
||||
def empty_1(self): # error
|
||||
...
|
||||
|
||||
def empty_2(self): # error
|
||||
pass
|
||||
|
||||
def empty_3(self): # error
|
||||
"""docstring"""
|
||||
...
|
||||
|
||||
def empty_4(self): # error
|
||||
"""multiple ellipsis/pass"""
|
||||
...
|
||||
pass
|
||||
...
|
||||
pass
|
||||
|
||||
@notabstract
|
||||
def abstract_0(self):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def abstract_1(self):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def abstract_2(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def abstract_3(self):
|
||||
...
|
||||
|
||||
def body_1(self):
|
||||
print("foo")
|
||||
...
|
||||
|
||||
def body_2(self):
|
||||
self.body_1()
|
||||
|
||||
|
||||
class NonAbstractClass:
|
||||
def empty_1(self): # safe
|
||||
...
|
||||
|
||||
def empty_2(self): # safe
|
||||
pass
|
||||
|
||||
|
||||
# ignore @overload, fixes issue #304
|
||||
# ignore overload with other imports, fixes #308
|
||||
import typing
|
||||
import typing as t
|
||||
import typing as anything
|
||||
from typing import Union, overload
|
||||
|
||||
|
||||
class AbstractClass(ABC):
|
||||
@overload
|
||||
def empty_1(self, foo: str):
|
||||
...
|
||||
|
||||
@typing.overload
|
||||
def empty_1(self, foo: int):
|
||||
...
|
||||
|
||||
@t.overload
|
||||
def empty_1(self, foo: list):
|
||||
...
|
||||
|
||||
@anything.overload
|
||||
def empty_1(self, foo: float):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def empty_1(self, foo: Union[str, int, list, float]):
|
||||
...
|
||||
55
resources/test/fixtures/BLE.py
vendored
Normal file
55
resources/test/fixtures/BLE.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
try:
|
||||
pass
|
||||
except ValueError:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except BaseException as e:
|
||||
raise e
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise e
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
pass
|
||||
except BaseException as e:
|
||||
raise e
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except Exception as e:
|
||||
try:
|
||||
raise e
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
try:
|
||||
pass
|
||||
except BaseException as e:
|
||||
raise e
|
||||
except Exception:
|
||||
pass
|
||||
2
resources/test/fixtures/C413.py
vendored
2
resources/test/fixtures/C413.py
vendored
@@ -1,4 +1,6 @@
|
||||
x = [2, 3, 1]
|
||||
list(x)
|
||||
list(sorted(x))
|
||||
reversed(sorted(x))
|
||||
reversed(sorted(x, key=lambda e: e))
|
||||
reversed(sorted(x, reverse=True))
|
||||
|
||||
138
resources/test/fixtures/C901.py
vendored
Normal file
138
resources/test/fixtures/C901.py
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
# Complexity = 1
|
||||
def trivial():
|
||||
pass
|
||||
|
||||
|
||||
# Complexity = 1
|
||||
def expr_as_statement():
|
||||
0xF00D
|
||||
|
||||
|
||||
# Complexity = 1
|
||||
def sequential(n):
|
||||
k = n + 4
|
||||
s = k + n
|
||||
return s
|
||||
|
||||
|
||||
# Complexity = 3
|
||||
def if_elif_else_dead_path(n):
|
||||
if n > 3:
|
||||
return "bigger than three"
|
||||
elif n > 4:
|
||||
return "is never executed"
|
||||
else:
|
||||
return "smaller than or equal to three"
|
||||
|
||||
|
||||
# Complexity = 3
|
||||
def nested_ifs():
|
||||
if n > 3:
|
||||
if n > 4:
|
||||
return "bigger than four"
|
||||
else:
|
||||
return "bigger than three"
|
||||
else:
|
||||
return "smaller than or equal to three"
|
||||
|
||||
|
||||
# Complexity = 2
|
||||
def for_loop():
|
||||
for i in range(10):
|
||||
print(i)
|
||||
|
||||
|
||||
# Complexity = 2
|
||||
def for_else(mylist):
|
||||
for i in mylist:
|
||||
print(i)
|
||||
else:
|
||||
print(None)
|
||||
|
||||
|
||||
# Complexity = 2
|
||||
def recursive(n):
|
||||
if n > 4:
|
||||
return f(n - 1)
|
||||
else:
|
||||
return n
|
||||
|
||||
|
||||
# Complexity = 3
|
||||
def nested_functions():
|
||||
def a():
|
||||
def b():
|
||||
pass
|
||||
|
||||
b()
|
||||
|
||||
a()
|
||||
|
||||
|
||||
# Complexity = 4
|
||||
def try_else():
|
||||
try:
|
||||
print(1)
|
||||
except TypeA:
|
||||
print(2)
|
||||
except TypeB:
|
||||
print(3)
|
||||
else:
|
||||
print(4)
|
||||
|
||||
|
||||
# Complexity = 3
|
||||
def nested_try_finally():
|
||||
try:
|
||||
try:
|
||||
print(1)
|
||||
finally:
|
||||
print(2)
|
||||
finally:
|
||||
print(3)
|
||||
|
||||
|
||||
# Complexity = 3
|
||||
async def foobar(a, b, c):
|
||||
await whatever(a, b, c)
|
||||
if await b:
|
||||
pass
|
||||
async with c:
|
||||
pass
|
||||
async for x in a:
|
||||
pass
|
||||
|
||||
|
||||
# Complexity = 1
|
||||
def annotated_assign():
|
||||
x: Any = None
|
||||
|
||||
|
||||
# Complexity = 9
|
||||
class Class:
|
||||
def handle(self, *args, **options):
|
||||
if args:
|
||||
return
|
||||
|
||||
class ServiceProvider:
|
||||
def a(self):
|
||||
pass
|
||||
|
||||
def b(self, data):
|
||||
if not args:
|
||||
pass
|
||||
|
||||
class Logger:
|
||||
def c(*args, **kwargs):
|
||||
pass
|
||||
|
||||
def error(self, message):
|
||||
pass
|
||||
|
||||
def info(self, message):
|
||||
pass
|
||||
|
||||
def exception(self):
|
||||
pass
|
||||
|
||||
return ServiceProvider(Logger())
|
||||
34
resources/test/fixtures/D.py
vendored
34
resources/test/fixtures/D.py
vendored
@@ -532,3 +532,37 @@ class Blah: # noqa: D203,D213
|
||||
|
||||
expect(os.path.normcase(__file__ if __file__[-1] != 'c' else __file__[:-1]),
|
||||
'D100: Missing docstring in public module')
|
||||
|
||||
|
||||
@expect('D201: No blank lines allowed before function docstring (found 1)')
|
||||
@expect('D213: Multi-line docstring summary should start at the second line')
|
||||
def multiline_leading_space():
|
||||
|
||||
"""Leading space.
|
||||
|
||||
More content.
|
||||
"""
|
||||
|
||||
|
||||
@expect('D202: No blank lines allowed after function docstring (found 1)')
|
||||
@expect('D213: Multi-line docstring summary should start at the second line')
|
||||
def multiline_trailing_space():
|
||||
"""Leading space.
|
||||
|
||||
More content.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@expect('D201: No blank lines allowed before function docstring (found 1)')
|
||||
@expect('D202: No blank lines allowed after function docstring (found 1)')
|
||||
@expect('D213: Multi-line docstring summary should start at the second line')
|
||||
def multiline_trailing_and_leading_space():
|
||||
|
||||
"""Trailing and leading space.
|
||||
|
||||
More content.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
2
resources/test/fixtures/E501.py
vendored
2
resources/test/fixtures/E501.py
vendored
@@ -5,7 +5,7 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
"""
|
||||
|
||||
_ = """Lorem ipsum dolor sit amet.
|
||||
_ = """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
|
||||
https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533
|
||||
|
||||
|
||||
3
resources/test/fixtures/E711.py
vendored
3
resources/test/fixtures/E711.py
vendored
@@ -23,6 +23,9 @@ if None != res[1]:
|
||||
if None == res[1]:
|
||||
pass
|
||||
|
||||
if x == None != None:
|
||||
pass
|
||||
|
||||
#: Okay
|
||||
if x not in y:
|
||||
pass
|
||||
|
||||
3
resources/test/fixtures/E712.py
vendored
3
resources/test/fixtures/E712.py
vendored
@@ -22,6 +22,9 @@ var = 1 if cond == True else -1 if cond == False else cond
|
||||
if (True) == TrueElement or x == TrueElement:
|
||||
pass
|
||||
|
||||
if res == True != False:
|
||||
pass
|
||||
|
||||
#: Okay
|
||||
if x not in y:
|
||||
pass
|
||||
|
||||
4
resources/test/fixtures/E731.py
vendored
4
resources/test/fixtures/E731.py
vendored
@@ -8,14 +8,14 @@ while False:
|
||||
|
||||
|
||||
f = object()
|
||||
#: E731
|
||||
f.method = lambda: "Method"
|
||||
|
||||
f = {}
|
||||
#: E731
|
||||
f["a"] = lambda x: x ** 2
|
||||
|
||||
f = []
|
||||
f.append(lambda x: x ** 2)
|
||||
|
||||
f = g = lambda x: x ** 2
|
||||
|
||||
lambda: "no-op"
|
||||
|
||||
1
resources/test/fixtures/F401_0.py
vendored
1
resources/test/fixtures/F401_0.py
vendored
@@ -28,7 +28,6 @@ from blah import ClassA, ClassB, ClassC
|
||||
if TYPE_CHECKING:
|
||||
from models import Fruit, Nut, Vegetable
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import shelve
|
||||
import importlib
|
||||
|
||||
20
resources/test/fixtures/F401_6.py
vendored
Normal file
20
resources/test/fixtures/F401_6.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
"""Test: explicit re-export."""
|
||||
|
||||
# OK
|
||||
from .applications import FastAPI as FastAPI
|
||||
|
||||
# F401 `background.BackgroundTasks` imported but unused
|
||||
from .background import BackgroundTasks
|
||||
|
||||
# F401 `datastructures.UploadFile` imported but unused
|
||||
from .datastructures import UploadFile as FileUpload
|
||||
|
||||
|
||||
# OK
|
||||
import applications as applications
|
||||
|
||||
# F401 `background` imported but unused
|
||||
import background
|
||||
|
||||
# F401 `datastructures` imported but unused
|
||||
import datastructures as structures
|
||||
24
resources/test/fixtures/F821_4.py
vendored
Normal file
24
resources/test/fixtures/F821_4.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
"""Test: import alias tracking."""
|
||||
from typing import List
|
||||
|
||||
_ = List["Model"]
|
||||
|
||||
|
||||
from typing import List as IList
|
||||
|
||||
_ = IList["Model"]
|
||||
|
||||
|
||||
from collections.abc import ItemsView
|
||||
|
||||
_ = ItemsView["Model"]
|
||||
|
||||
|
||||
import collections.abc
|
||||
|
||||
_ = collections.abc.ItemsView["Model"]
|
||||
|
||||
|
||||
from collections import abc
|
||||
|
||||
_ = abc.ItemsView["Model"]
|
||||
14
resources/test/fixtures/F821_5.py
vendored
Normal file
14
resources/test/fixtures/F821_5.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"""Test: inner class annotation."""
|
||||
|
||||
|
||||
class RandomClass:
|
||||
def random_func(self) -> "InnerClass":
|
||||
pass
|
||||
|
||||
|
||||
class OuterClass:
|
||||
class InnerClass:
|
||||
pass
|
||||
|
||||
def failing_func(self) -> "InnerClass":
|
||||
return self.InnerClass()
|
||||
22
resources/test/fixtures/F841.py
vendored
22
resources/test/fixtures/F841.py
vendored
@@ -35,3 +35,25 @@ def f4():
|
||||
_ = 1
|
||||
__ = 1
|
||||
_discarded = 1
|
||||
|
||||
|
||||
a = 1
|
||||
|
||||
|
||||
def f5():
|
||||
global a
|
||||
|
||||
# Used in `f7` via `nonlocal`.
|
||||
b = 1
|
||||
|
||||
def f6():
|
||||
# F841
|
||||
b = 1
|
||||
|
||||
def f7():
|
||||
nonlocal b
|
||||
|
||||
|
||||
def f6():
|
||||
annotations = []
|
||||
assert len([annotations for annotations in annotations])
|
||||
|
||||
42
resources/test/fixtures/FBT.py
vendored
Normal file
42
resources/test/fixtures/FBT.py
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
def function(
|
||||
posonly_nohint,
|
||||
posonly_nonboolhint: int,
|
||||
posonly_boolhint: bool,
|
||||
posonly_boolstrhint: "bool",
|
||||
/,
|
||||
offset,
|
||||
posorkw_nonvalued_nohint,
|
||||
posorkw_nonvalued_nonboolhint: int,
|
||||
posorkw_nonvalued_boolhint: bool,
|
||||
posorkw_nonvalued_boolstrhint: "bool",
|
||||
posorkw_boolvalued_nohint=True,
|
||||
posorkw_boolvalued_nonboolhint: int = True,
|
||||
posorkw_boolvalued_boolhint: bool = True,
|
||||
posorkw_boolvalued_boolstrhint: "bool" = True,
|
||||
posorkw_nonboolvalued_nohint=1,
|
||||
posorkw_nonboolvalued_nonboolhint: int = 2,
|
||||
posorkw_nonboolvalued_boolhint: bool = 3,
|
||||
posorkw_nonboolvalued_boolstrhint: "bool" = 4,
|
||||
*,
|
||||
kwonly_nonvalued_nohint,
|
||||
kwonly_nonvalued_nonboolhint: int,
|
||||
kwonly_nonvalued_boolhint: bool,
|
||||
kwonly_nonvalued_boolstrhint: "bool",
|
||||
kwonly_boolvalued_nohint=True,
|
||||
kwonly_boolvalued_nonboolhint: int = False,
|
||||
kwonly_boolvalued_boolhint: bool = True,
|
||||
kwonly_boolvalued_boolstrhint: "bool" = True,
|
||||
kwonly_nonboolvalued_nohint=5,
|
||||
kwonly_nonboolvalued_nonboolhint: int = 1,
|
||||
kwonly_nonboolvalued_boolhint: bool = 1,
|
||||
kwonly_nonboolvalued_boolstrhint: "bool" = 1,
|
||||
**kw,
|
||||
):
|
||||
...
|
||||
|
||||
|
||||
def used(do):
|
||||
return do
|
||||
|
||||
used("a", True)
|
||||
used(do=True)
|
||||
12
resources/test/fixtures/I252.py
vendored
Normal file
12
resources/test/fixtures/I252.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
from . import sibling
|
||||
from .sibling import example
|
||||
|
||||
from .. import parent
|
||||
from ..parent import example
|
||||
|
||||
from ... import grandparent
|
||||
from ...grandparent import example
|
||||
|
||||
import other
|
||||
import other.example
|
||||
from other import example
|
||||
8
resources/test/fixtures/M001.py
vendored
8
resources/test/fixtures/M001.py
vendored
@@ -18,6 +18,14 @@ def f() -> None:
|
||||
# Invalid (and unimplemented)
|
||||
d = 1 # noqa: F841, W191
|
||||
|
||||
# fmt: off
|
||||
# Invalid - no space before #
|
||||
d = 1# noqa: E501
|
||||
|
||||
# Invalid - many spaces before #
|
||||
d = 1 # noqa: E501
|
||||
# fmt: on
|
||||
|
||||
|
||||
# Valid
|
||||
_ = """Lorem ipsum dolor sit amet.
|
||||
|
||||
8
resources/test/fixtures/N804.py
vendored
8
resources/test/fixtures/N804.py
vendored
@@ -30,6 +30,14 @@ class Class:
|
||||
def __init_subclass__(self, default_name, **kwargs):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
def class_method_with_positional_only_argument(cls, x, /, other):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
def bad_class_method_with_positional_only_argument(self, x, /, other):
|
||||
...
|
||||
|
||||
|
||||
class MetaClass(ABCMeta):
|
||||
def bad_method(self):
|
||||
|
||||
10
resources/test/fixtures/N805.py
vendored
10
resources/test/fixtures/N805.py
vendored
@@ -1,5 +1,7 @@
|
||||
from abc import ABCMeta
|
||||
|
||||
import pydantic
|
||||
|
||||
|
||||
class Class:
|
||||
def bad_method(this):
|
||||
@@ -21,6 +23,14 @@ class Class:
|
||||
def static_method(x):
|
||||
return x
|
||||
|
||||
@pydantic.validator
|
||||
def lower(cls, my_field: str) -> str:
|
||||
pass
|
||||
|
||||
@pydantic.validator("my_field")
|
||||
def lower(cls, my_field: str) -> str:
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
|
||||
10
resources/test/fixtures/N806.py
vendored
10
resources/test/fixtures/N806.py
vendored
@@ -1,5 +1,15 @@
|
||||
import collections
|
||||
from collections import namedtuple
|
||||
|
||||
GLOBAL: str = "foo"
|
||||
|
||||
|
||||
def f():
|
||||
global GLOBAL
|
||||
GLOBAL = "bar"
|
||||
lower = 0
|
||||
Camel = 0
|
||||
CONSTANT = 0
|
||||
_ = 0
|
||||
MyObj1 = collections.namedtuple("MyObj1", ["a", "b"])
|
||||
MyObj2 = namedtuple("MyObj12", ["a", "b"])
|
||||
|
||||
21
resources/test/fixtures/N807.py
vendored
21
resources/test/fixtures/N807.py
vendored
@@ -10,6 +10,27 @@ def good__():
|
||||
pass
|
||||
|
||||
|
||||
def nested():
|
||||
def __bad__():
|
||||
pass
|
||||
|
||||
def __good():
|
||||
pass
|
||||
|
||||
def good__():
|
||||
pass
|
||||
|
||||
|
||||
class Class:
|
||||
def __good__(self):
|
||||
pass
|
||||
|
||||
|
||||
# https://peps.python.org/pep-0562/
|
||||
def __getattr__(name):
|
||||
pass
|
||||
|
||||
|
||||
# https://peps.python.org/pep-0562/
|
||||
def __dir__():
|
||||
pass
|
||||
|
||||
6
resources/test/fixtures/N815.py
vendored
6
resources/test/fixtures/N815.py
vendored
@@ -1,6 +1,12 @@
|
||||
import collections
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
class C:
|
||||
lower = 0
|
||||
CONSTANT = 0
|
||||
mixedCase = 0
|
||||
_mixedCase = 0
|
||||
mixed_Case = 0
|
||||
myObj1 = collections.namedtuple("MyObj1", ["a", "b"])
|
||||
myObj2 = namedtuple("MyObj2", ["a", "b"])
|
||||
|
||||
5
resources/test/fixtures/N816.py
vendored
5
resources/test/fixtures/N816.py
vendored
@@ -1,5 +1,10 @@
|
||||
import collections
|
||||
from collections import namedtuple
|
||||
|
||||
lower = 0
|
||||
CONSTANT = 0
|
||||
mixedCase = 0
|
||||
_mixedCase = 0
|
||||
mixed_Case = 0
|
||||
myObj1 = collections.namedtuple("MyObj1", ["a", "b"])
|
||||
myObj2 = namedtuple("MyObj2", ["a", "b"])
|
||||
|
||||
8
resources/test/fixtures/N818.py
vendored
8
resources/test/fixtures/N818.py
vendored
@@ -8,3 +8,11 @@ class AnotherError(Exception):
|
||||
|
||||
class C(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class D(BaseException):
|
||||
pass
|
||||
|
||||
|
||||
class E(AnotherError):
|
||||
pass
|
||||
|
||||
3
resources/test/fixtures/RUF001.py
vendored
3
resources/test/fixtures/RUF001.py
vendored
@@ -2,5 +2,6 @@ x = "𝐁ad string"
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a comment with an unusual parenthesis: )"""
|
||||
"""Here's a docstring with an unusual parenthesis: )"""
|
||||
# And here's a comment with an unusual punctuation mark: ᜵
|
||||
...
|
||||
|
||||
3
resources/test/fixtures/RUF002.py
vendored
3
resources/test/fixtures/RUF002.py
vendored
@@ -2,5 +2,6 @@ x = "𝐁ad string"
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a comment with an unusual parenthesis: )"""
|
||||
"""Here's a docstring with an unusual parenthesis: )"""
|
||||
# And here's a comment with an unusual punctuation mark: ᜵
|
||||
...
|
||||
|
||||
7
resources/test/fixtures/RUF003.py
vendored
Normal file
7
resources/test/fixtures/RUF003.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
x = "𝐁ad string"
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a docstring with an unusual parenthesis: )"""
|
||||
# And here's a comment with an unusual punctuation mark: ᜵
|
||||
...
|
||||
5
resources/test/fixtures/RUF101_0.py
vendored
Normal file
5
resources/test/fixtures/RUF101_0.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(2)
|
||||
10
resources/test/fixtures/RUF101_1.py
vendored
Normal file
10
resources/test/fixtures/RUF101_1.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import sys
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(1)
|
||||
|
||||
|
||||
sys.exit(2)
|
||||
7
resources/test/fixtures/RUF101_2.py
vendored
Normal file
7
resources/test/fixtures/RUF101_2.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import sys as sys2
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(1)
|
||||
7
resources/test/fixtures/RUF101_3.py
vendored
Normal file
7
resources/test/fixtures/RUF101_3.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
from sys import exit
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(1)
|
||||
7
resources/test/fixtures/RUF101_4.py
vendored
Normal file
7
resources/test/fixtures/RUF101_4.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
from sys import exit as exit2
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(1)
|
||||
7
resources/test/fixtures/RUF101_5.py
vendored
Normal file
7
resources/test/fixtures/RUF101_5.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
from sys import *
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
exit(1)
|
||||
12
resources/test/fixtures/RUF101_6.py
vendored
Normal file
12
resources/test/fixtures/RUF101_6.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
exit(0)
|
||||
|
||||
|
||||
def exit(e):
|
||||
pass
|
||||
|
||||
|
||||
exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
exit(2)
|
||||
11
resources/test/fixtures/S101.py
vendored
Normal file
11
resources/test/fixtures/S101.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Error
|
||||
assert True
|
||||
|
||||
def fn():
|
||||
x = 1
|
||||
|
||||
# Error
|
||||
assert x == 1
|
||||
|
||||
# Error
|
||||
assert x == 2
|
||||
5
resources/test/fixtures/S102.py
vendored
Normal file
5
resources/test/fixtures/S102.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
def fn():
|
||||
# Error
|
||||
exec('x = 2')
|
||||
|
||||
exec('y = 3')
|
||||
19
resources/test/fixtures/S104.py
vendored
Normal file
19
resources/test/fixtures/S104.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
def func(address):
|
||||
print(address)
|
||||
|
||||
|
||||
# OK
|
||||
"OK"
|
||||
|
||||
# Error
|
||||
"0.0.0.0"
|
||||
'0.0.0.0'
|
||||
|
||||
|
||||
# Error
|
||||
func("0.0.0.0")
|
||||
|
||||
|
||||
def my_func():
|
||||
x = "0.0.0.0"
|
||||
print(x)
|
||||
53
resources/test/fixtures/S105.py
vendored
Normal file
53
resources/test/fixtures/S105.py
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
d = {}
|
||||
|
||||
# OK
|
||||
safe = "s3cr3t"
|
||||
password = True
|
||||
password = safe
|
||||
password is True
|
||||
password == 1
|
||||
d["safe"] = "s3cr3t"
|
||||
|
||||
# Errors
|
||||
password = "s3cr3t"
|
||||
_pass = "s3cr3t"
|
||||
passwd = "s3cr3t"
|
||||
pwd = "s3cr3t"
|
||||
secret = "s3cr3t"
|
||||
token = "s3cr3t"
|
||||
secrete = "s3cr3t"
|
||||
safe = password = "s3cr3t"
|
||||
password = safe = "s3cr3t"
|
||||
|
||||
d["password"] = "s3cr3t"
|
||||
d["pass"] = "s3cr3t"
|
||||
d["passwd"] = "s3cr3t"
|
||||
d["pwd"] = "s3cr3t"
|
||||
d["secret"] = "s3cr3t"
|
||||
d["token"] = "s3cr3t"
|
||||
d["secrete"] = "s3cr3t"
|
||||
safe = d["password"] = "s3cr3t"
|
||||
d["password"] = safe = "s3cr3t"
|
||||
|
||||
|
||||
class MyClass:
|
||||
password = "s3cr3t"
|
||||
safe = password
|
||||
|
||||
|
||||
MyClass.password = "s3cr3t"
|
||||
MyClass._pass = "s3cr3t"
|
||||
MyClass.passwd = "s3cr3t"
|
||||
MyClass.pwd = "s3cr3t"
|
||||
MyClass.secret = "s3cr3t"
|
||||
MyClass.token = "s3cr3t"
|
||||
MyClass.secrete = "s3cr3t"
|
||||
|
||||
password == "s3cr3t"
|
||||
_pass == "s3cr3t"
|
||||
passwd == "s3cr3t"
|
||||
pwd == "s3cr3t"
|
||||
secret == "s3cr3t"
|
||||
token == "s3cr3t"
|
||||
secrete == "s3cr3t"
|
||||
password == safe == "s3cr3t"
|
||||
13
resources/test/fixtures/S106.py
vendored
Normal file
13
resources/test/fixtures/S106.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
def func(pos, password):
|
||||
pass
|
||||
|
||||
|
||||
string = "Hello World"
|
||||
|
||||
# OK
|
||||
func("s3cr3t")
|
||||
func(1, password=string)
|
||||
func(pos="s3cr3t", password=string)
|
||||
|
||||
# Error
|
||||
func(1, password="s3cr3t")
|
||||
30
resources/test/fixtures/S107.py
vendored
Normal file
30
resources/test/fixtures/S107.py
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
def ok(first, default="default"):
|
||||
pass
|
||||
|
||||
|
||||
def default(first, password="default"):
|
||||
pass
|
||||
|
||||
|
||||
def ok_posonly(first, /, pos, default="posonly"):
|
||||
pass
|
||||
|
||||
|
||||
def default_posonly(first, /, pos, password="posonly"):
|
||||
pass
|
||||
|
||||
|
||||
def ok_kwonly(first, *, default="kwonly"):
|
||||
pass
|
||||
|
||||
|
||||
def default_kwonly(first, *, password="kwonly"):
|
||||
pass
|
||||
|
||||
|
||||
def ok_all(first, /, pos, default="posonly", *, kwonly="kwonly"):
|
||||
pass
|
||||
|
||||
|
||||
def default_all(first, /, pos, secret="posonly", *, password="kwonly"):
|
||||
pass
|
||||
15
resources/test/fixtures/U002.py
vendored
15
resources/test/fixtures/U002.py
vendored
@@ -1,15 +0,0 @@
|
||||
from os.path import abspath
|
||||
|
||||
x = abspath(__file__)
|
||||
|
||||
|
||||
import os
|
||||
|
||||
|
||||
y = os.path.abspath(__file__)
|
||||
|
||||
|
||||
from os import path
|
||||
|
||||
|
||||
z = path.abspath(__file__)
|
||||
22
resources/test/fixtures/U006.py
vendored
22
resources/test/fixtures/U006.py
vendored
@@ -1,3 +1,10 @@
|
||||
import typing
|
||||
|
||||
|
||||
def f(x: typing.List[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
from typing import List
|
||||
|
||||
|
||||
@@ -5,8 +12,19 @@ def f(x: List[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
import typing
|
||||
import typing as t
|
||||
|
||||
|
||||
def f(x: typing.List[str]) -> None:
|
||||
def f(x: t.List[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
from typing import List as IList
|
||||
|
||||
|
||||
def f(x: IList[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: "List[str]") -> None:
|
||||
...
|
||||
|
||||
29
resources/test/fixtures/U007.py
vendored
29
resources/test/fixtures/U007.py
vendored
@@ -1,40 +1,43 @@
|
||||
import typing
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
|
||||
def f(x: Optional[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
def f(x: typing.Optional[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
from typing import Union
|
||||
|
||||
|
||||
def f(x: Union[str, int, Union[float, bytes]]) -> None:
|
||||
...
|
||||
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
def f(x: typing.Union[str, int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
from typing import Union
|
||||
def f(x: typing.Union[(str, int)]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[(str, int), float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: "Union[str, int, Union[float, bytes]]") -> None:
|
||||
...
|
||||
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
def f(x: "typing.Union[str, int]") -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union["str", int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[("str", "int"), float]) -> None:
|
||||
...
|
||||
|
||||
14
resources/test/fixtures/U010.py
vendored
Normal file
14
resources/test/fixtures/U010.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
from __future__ import nested_scopes, generators
|
||||
from __future__ import with_statement, unicode_literals
|
||||
from __future__ import absolute_import, division
|
||||
from __future__ import generator_stop
|
||||
from __future__ import print_function, generator_stop
|
||||
from __future__ import invalid_module, generators
|
||||
|
||||
if True:
|
||||
from __future__ import generator_stop
|
||||
from __future__ import generators
|
||||
|
||||
if True:
|
||||
from __future__ import generator_stop
|
||||
from __future__ import invalid_module, generators
|
||||
103
resources/test/fixtures/U011_0.py
vendored
Normal file
103
resources/test/fixtures/U011_0.py
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
import functools
|
||||
from functools import lru_cache
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def fixme1():
|
||||
pass
|
||||
|
||||
|
||||
@other_deco_after
|
||||
@functools.lru_cache()
|
||||
def fixme2():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def fixme3():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
@other_deco_before
|
||||
def fixme4():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache( # A
|
||||
) # B
|
||||
def fixme5():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache(
|
||||
# A
|
||||
) # B
|
||||
def fixme6():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache(
|
||||
# A
|
||||
maxsize = None) # B
|
||||
def fixme7():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache(
|
||||
# A1
|
||||
maxsize = None
|
||||
# A2
|
||||
) # B
|
||||
def fixme8():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache(
|
||||
# A1
|
||||
maxsize =
|
||||
None
|
||||
# A2
|
||||
|
||||
)
|
||||
def fixme9():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache(
|
||||
# A1
|
||||
maxsize =
|
||||
None
|
||||
# A2
|
||||
)
|
||||
def fixme10():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache
|
||||
def correct1():
|
||||
pass
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def correct2():
|
||||
pass
|
||||
|
||||
|
||||
@functoools.lru_cache(maxsize=64)
|
||||
def correct3():
|
||||
pass
|
||||
|
||||
|
||||
def user_func():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache(user_func)
|
||||
def correct4():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache(user_func, maxsize=None)
|
||||
def correct5():
|
||||
pass
|
||||
15
resources/test/fixtures/U011_1.py
vendored
Normal file
15
resources/test/fixtures/U011_1.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import functools
|
||||
|
||||
|
||||
def lru_cache(maxsize=None):
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def dont_fixme():
|
||||
pass
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def dont_fixme():
|
||||
pass
|
||||
52
resources/test/fixtures/U012.py
vendored
Normal file
52
resources/test/fixtures/U012.py
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# ASCII literals should be replaced by a bytes literal
|
||||
"foo".encode("utf-8") # b"foo"
|
||||
"foo".encode("u8") # b"foo"
|
||||
"foo".encode() # b"foo"
|
||||
"foo".encode("UTF8") # b"foo"
|
||||
U"foo".encode("utf-8") # b"foo"
|
||||
"foo".encode(encoding="utf-8") # b"foo"
|
||||
"""
|
||||
Lorem
|
||||
|
||||
Ipsum
|
||||
""".encode(
|
||||
"utf-8"
|
||||
)
|
||||
# b"""
|
||||
# Lorem
|
||||
#
|
||||
# Ipsum
|
||||
# """
|
||||
|
||||
# `encode` on variables should not be processed.
|
||||
string = "hello there"
|
||||
string.encode("utf-8")
|
||||
|
||||
bar = "bar"
|
||||
f"foo{bar}".encode("utf-8") # f"foo{bar}".encode()
|
||||
encoding = "latin"
|
||||
"foo".encode(encoding)
|
||||
f"foo{bar}".encode(encoding)
|
||||
|
||||
# `encode` with custom args and kwargs should not be processed.
|
||||
"foo".encode("utf-8", errors="replace")
|
||||
"foo".encode("utf-8", "replace")
|
||||
"foo".encode(errors="replace")
|
||||
"foo".encode(encoding="utf-8", errors="replace")
|
||||
|
||||
# `encode` with custom args and kwargs on unicode should not be processed.
|
||||
"unicode text©".encode("utf-8", errors="replace")
|
||||
"unicode text©".encode("utf-8", "replace")
|
||||
"unicode text©".encode(errors="replace")
|
||||
"unicode text©".encode(encoding="utf-8", errors="replace")
|
||||
|
||||
# Unicode literals should only be stripped of default encoding.
|
||||
"unicode text©".encode("utf-8") # "unicode text©".encode()
|
||||
"unicode text©".encode()
|
||||
"unicode text©".encode(encoding="UTF8") # "unicode text©".encode()
|
||||
|
||||
r"fo\o".encode("utf-8") # br"fo\o"
|
||||
u"foo".encode("utf-8") # b"foo"
|
||||
R"fo\o".encode("utf-8") # br"fo\o"
|
||||
U"foo".encode("utf-8") # b"foo"
|
||||
print("foo".encode()) # print(b"foo")
|
||||
33
resources/test/fixtures/U013.py
vendored
Normal file
33
resources/test/fixtures/U013.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
from typing import TypedDict, NotRequired, Literal
|
||||
import typing
|
||||
|
||||
# dict literal
|
||||
MyType1 = TypedDict("MyType1", {"a": int, "b": str})
|
||||
|
||||
# dict call
|
||||
MyType2 = TypedDict("MyType2", dict(a=int, b=str))
|
||||
|
||||
# kwargs
|
||||
MyType3 = TypedDict("MyType3", a=int, b=str)
|
||||
|
||||
# Empty TypedDict
|
||||
MyType4 = TypedDict("MyType4")
|
||||
|
||||
# Literal values
|
||||
MyType5 = TypedDict("MyType5", {"a": "hello"})
|
||||
MyType6 = TypedDict("MyType6", a="hello")
|
||||
|
||||
# NotRequired
|
||||
MyType7 = TypedDict("MyType7", {"a": NotRequired[dict]})
|
||||
|
||||
# total
|
||||
MyType8 = TypedDict("MyType8", {"x": int, "y": int}, total=False)
|
||||
|
||||
# invalid identifiers
|
||||
MyType9 = TypedDict("MyType9", {"in": int, "x-y": int})
|
||||
|
||||
# using Literal type
|
||||
MyType10 = TypedDict("MyType10", {"key": Literal["value"]})
|
||||
|
||||
# using namespace TypedDict
|
||||
MyType11 = typing.TypedDict("MyType11", {"key": int})
|
||||
22
resources/test/fixtures/U014.py
vendored
Normal file
22
resources/test/fixtures/U014.py
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
from typing import NamedTuple
|
||||
import typing
|
||||
|
||||
# with complex annotations
|
||||
NT1 = NamedTuple("NT1", [("a", int), ("b", tuple[str, ...])])
|
||||
|
||||
# with default values as list
|
||||
NT2 = NamedTuple(
|
||||
"NT2",
|
||||
[("a", int), ("b", str), ("c", list[bool])],
|
||||
defaults=["foo", [True]],
|
||||
)
|
||||
|
||||
# with namespace
|
||||
NT3 = typing.NamedTuple("NT3", [("a", int), ("b", str)])
|
||||
|
||||
# with too many default values
|
||||
NT4 = NamedTuple(
|
||||
"NT4",
|
||||
[("a", int), ("b", str)],
|
||||
defaults=[1, "bar", "baz"],
|
||||
)
|
||||
38
resources/test/fixtures/U015.py
vendored
Normal file
38
resources/test/fixtures/U015.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
open("foo", "U")
|
||||
open("foo", "Ur")
|
||||
open("foo", "Ub")
|
||||
open("foo", "rUb")
|
||||
open("foo", "r")
|
||||
open("foo", "rt")
|
||||
open("f", "r", encoding="UTF-8")
|
||||
open("f", "wt")
|
||||
|
||||
with open("foo", "U") as f:
|
||||
pass
|
||||
with open("foo", "Ur") as f:
|
||||
pass
|
||||
with open("foo", "Ub") as f:
|
||||
pass
|
||||
with open("foo", "rUb") as f:
|
||||
pass
|
||||
with open("foo", "r") as f:
|
||||
pass
|
||||
with open("foo", "rt") as f:
|
||||
pass
|
||||
with open("foo", "r", encoding="UTF-8") as f:
|
||||
pass
|
||||
with open("foo", "wt") as f:
|
||||
pass
|
||||
|
||||
open(f("a", "b", "c"), "U")
|
||||
open(f("a", "b", "c"), "Ub")
|
||||
|
||||
with open(f("a", "b", "c"), "U") as f:
|
||||
pass
|
||||
with open(f("a", "b", "c"), "Ub") as f:
|
||||
pass
|
||||
|
||||
with open("foo", "U") as fa, open("bar", "U") as fb:
|
||||
pass
|
||||
with open("foo", "Ub") as fa, open("bar", "Ub") as fb:
|
||||
pass
|
||||
12
resources/test/fixtures/YTT101.py
vendored
Normal file
12
resources/test/fixtures/YTT101.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import sys
|
||||
from sys import version, version as v
|
||||
|
||||
print(sys.version)
|
||||
|
||||
print(sys.version[:3])
|
||||
print(version[:3])
|
||||
print(v[:3])
|
||||
|
||||
# the tool is timid and only flags certain numeric slices
|
||||
i = 3
|
||||
print(sys.version[:i])
|
||||
5
resources/test/fixtures/YTT102.py
vendored
Normal file
5
resources/test/fixtures/YTT102.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
from sys import version
|
||||
|
||||
py_minor = sys.version[2]
|
||||
py_minor = version[2]
|
||||
8
resources/test/fixtures/YTT103.py
vendored
Normal file
8
resources/test/fixtures/YTT103.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import sys
|
||||
from sys import version
|
||||
|
||||
version < "3.5"
|
||||
sys.version < "3.5"
|
||||
sys.version <= "3.5"
|
||||
sys.version > "3.5"
|
||||
sys.version >= "3.5"
|
||||
10
resources/test/fixtures/YTT201.py
vendored
Normal file
10
resources/test/fixtures/YTT201.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import sys
|
||||
from sys import version_info
|
||||
|
||||
print("{}.{}".format(*sys.version_info))
|
||||
PY3 = sys.version_info[0] >= 3
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
PY3 = version_info[0] == 3
|
||||
PY2 = sys.version_info[0] != 3
|
||||
PY2 = version_info[0] != 3
|
||||
7
resources/test/fixtures/YTT202.py
vendored
Normal file
7
resources/test/fixtures/YTT202.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import six
|
||||
from six import PY3
|
||||
|
||||
if six.PY3:
|
||||
print("3")
|
||||
if PY3:
|
||||
print("3")
|
||||
5
resources/test/fixtures/YTT203.py
vendored
Normal file
5
resources/test/fixtures/YTT203.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
from sys import version_info
|
||||
|
||||
sys.version_info[1] >= 5
|
||||
version_info[1] < 6
|
||||
5
resources/test/fixtures/YTT204.py
vendored
Normal file
5
resources/test/fixtures/YTT204.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
from sys import version_info
|
||||
|
||||
sys.version_info.minor <= 7
|
||||
version_info.minor > 8
|
||||
5
resources/test/fixtures/YTT301.py
vendored
Normal file
5
resources/test/fixtures/YTT301.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
from sys import version
|
||||
|
||||
py_major = sys.version[0]
|
||||
py_major = version[0]
|
||||
8
resources/test/fixtures/YTT302.py
vendored
Normal file
8
resources/test/fixtures/YTT302.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import sys
|
||||
from sys import version
|
||||
|
||||
version < "3"
|
||||
sys.version < "3"
|
||||
sys.version <= "3"
|
||||
sys.version > "3"
|
||||
sys.version >= "3"
|
||||
5
resources/test/fixtures/YTT303.py
vendored
Normal file
5
resources/test/fixtures/YTT303.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import sys
|
||||
from sys import version
|
||||
|
||||
print(sys.version[:1])
|
||||
print(version[:1])
|
||||
9
resources/test/fixtures/excluded.py
vendored
9
resources/test/fixtures/excluded.py
vendored
@@ -1,9 +0,0 @@
|
||||
a = "abc"
|
||||
b = f"ghi{'jkl'}"
|
||||
|
||||
c = f"def"
|
||||
d = f"def" + "ghi"
|
||||
e = (
|
||||
f"def" +
|
||||
"ghi"
|
||||
)
|
||||
57
resources/test/fixtures/flake8_annotations/allow_star_arg_any.py
vendored
Normal file
57
resources/test/fixtures/flake8_annotations/allow_star_arg_any.py
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
# OK
|
||||
def foo(a: int, *args: str, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: Any, *args: str, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: str, **kwargs: str) -> Any:
|
||||
pass
|
||||
|
||||
|
||||
# OK
|
||||
def foo(a: int, *args: Any, **kwargs: Any) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# OK
|
||||
def foo(a: int, *args: Any, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: str, **kwargs: Any) -> int:
|
||||
pass
|
||||
|
||||
|
||||
class Bar:
|
||||
# OK
|
||||
def foo_method(self, a: int, *params: str, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo_method(self, a: Any, *params: str, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo_method(self, a: int, *params: str, **options: str) -> Any:
|
||||
pass
|
||||
|
||||
# OK
|
||||
def foo_method(self, a: int, *params: Any, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# OK
|
||||
def foo_method(self, a: int, *params: Any, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# OK
|
||||
def foo_method(self, a: int, *params: str, **options: Any) -> int:
|
||||
pass
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Type
|
||||
from typing import Any, Type
|
||||
|
||||
# Error
|
||||
def foo(a, b):
|
||||
@@ -35,6 +35,36 @@ def foo() -> int:
|
||||
pass
|
||||
|
||||
|
||||
# OK
|
||||
def foo(a: int, *args: str, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: Any, *args: str, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: str, **kwargs: str) -> Any:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: Any, **kwargs: Any) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: Any, **kwargs: str) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# ANN401
|
||||
def foo(a: int, *args: str, **kwargs: Any) -> int:
|
||||
pass
|
||||
|
||||
|
||||
class Foo:
|
||||
# OK
|
||||
def foo(self: "Foo", a: int, b: int) -> int:
|
||||
@@ -44,6 +74,26 @@ class Foo:
|
||||
def foo(self, a: int, b: int) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo(self: "Foo", a: Any, *params: str, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo(self: "Foo", a: int, *params: str, **options: str) -> Any:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo(self: "Foo", a: int, *params: Any, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo(self: "Foo", a: int, *params: Any, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
def foo(self: "Foo", a: int, *params: str, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# OK
|
||||
@classmethod
|
||||
def foo(cls: Type["Foo"], a: int, b: int) -> int:
|
||||
|
||||
7
resources/test/fixtures/isort/add_newline_before_comments.py
vendored
Normal file
7
resources/test/fixtures/isort/add_newline_before_comments.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
# This is a comment in the same section, so we need to add one newline.
|
||||
import sys
|
||||
import numpy as np
|
||||
# This is a comment, but it starts a new section, so we don't need to add a newline
|
||||
# before it.
|
||||
import leading_prefix
|
||||
5
resources/test/fixtures/isort/combine_import_froms.py
vendored
Normal file
5
resources/test/fixtures/isort/combine_import_froms.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
from collections import Awaitable
|
||||
from collections import AsyncIterable
|
||||
from collections import Collection
|
||||
from collections import ChainMap
|
||||
from collections import MutableSequence, MutableMapping
|
||||
25
resources/test/fixtures/isort/comments.py
vendored
Normal file
25
resources/test/fixtures/isort/comments.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Comment 1
|
||||
# Comment 2
|
||||
import D
|
||||
|
||||
# Comment 3a
|
||||
import C
|
||||
|
||||
# Comment 3b
|
||||
import C
|
||||
|
||||
import B # Comment 4
|
||||
|
||||
# Comment 5
|
||||
|
||||
# Comment 6
|
||||
from A import (
|
||||
a, # Comment 7
|
||||
b,
|
||||
c, # Comment 8
|
||||
)
|
||||
from A import (
|
||||
a, # Comment 9
|
||||
b, # Comment 10
|
||||
c, # Comment 11
|
||||
)
|
||||
4
resources/test/fixtures/isort/deduplicate_imports.py
vendored
Normal file
4
resources/test/fixtures/isort/deduplicate_imports.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import os
|
||||
import os
|
||||
import os as os1
|
||||
import os as os2
|
||||
14
resources/test/fixtures/isort/fit_line_length.py
vendored
Normal file
14
resources/test/fixtures/isort/fit_line_length.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
from line_with_88 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_89 import (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||
)
|
||||
|
||||
if indented:
|
||||
from line_with_88 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_89 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_90 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_91 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_92 import aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
from line_with_93 import (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||
)
|
||||
4
resources/test/fixtures/isort/fit_line_length_comment.py
vendored
Normal file
4
resources/test/fixtures/isort/fit_line_length_comment.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import a
|
||||
# Don't take this comment into account when determining whether the next import can fit on one line.
|
||||
from b import c
|
||||
from d import e # Do take this comment into account when determining whether the next import can fit on one line.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user