Compare commits
210 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea9acda732 | ||
|
|
6c8021e970 | ||
|
|
61b6ad46ea | ||
|
|
041d8108e6 | ||
|
|
e2c4a098de | ||
|
|
e865f58426 | ||
|
|
23b4e16b1d | ||
|
|
ae2ac905dc | ||
|
|
55619b321a | ||
|
|
6f31b002f8 | ||
|
|
1a79965aa0 | ||
|
|
16da183f8e | ||
|
|
3f689917cb | ||
|
|
a4a215e8a3 | ||
|
|
aa1c884910 | ||
|
|
7fb55c6d99 | ||
|
|
04ea523ad8 | ||
|
|
9897f81cf3 | ||
|
|
1a2559b001 | ||
|
|
721a1e9443 | ||
|
|
f38bba18ee | ||
|
|
14cf36f922 | ||
|
|
d28e026525 | ||
|
|
d19a8aa54d | ||
|
|
f299940452 | ||
|
|
e1ab7163ac | ||
|
|
9edc479c6c | ||
|
|
560558b814 | ||
|
|
bef601b994 | ||
|
|
7445d00b88 | ||
|
|
7c78d4e103 | ||
|
|
8b14f1b8cc | ||
|
|
5a6b51e623 | ||
|
|
0b60242fb7 | ||
|
|
65b77feeb8 | ||
|
|
04b9c0a31d | ||
|
|
49dc8231be | ||
|
|
92ca114882 | ||
|
|
553bc7443a | ||
|
|
a3af6c1ea5 | ||
|
|
b50016fe89 | ||
|
|
2cf2805848 | ||
|
|
33fbef7700 | ||
|
|
68668a584b | ||
|
|
6cd8655d29 | ||
|
|
72a9bd3cfb | ||
|
|
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 |
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
|
||||
|
||||
11
.github/workflows/ruff.yaml
vendored
11
.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 }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.115
|
||||
rev: v0.0.143
|
||||
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
|
||||
|
||||
720
Cargo.lock
generated
720
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
20
Cargo.toml
20
Cargo.toml
@@ -6,27 +6,31 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.115"
|
||||
version = "0.0.143"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
|
||||
[dependencies]
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
anyhow = { version = "1.0.66" }
|
||||
atty = { version = "0.2.14" }
|
||||
bincode = { version = "1.3.3" }
|
||||
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"] }
|
||||
clap_complete_command = "0.4.0"
|
||||
colored = { version = "2.0.0" }
|
||||
common-path = { version = "1.0.0" }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
filetime = { version = "0.2.17" }
|
||||
fnv = { version = "1.0.7" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = {version = "0.4.9" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "a13ec97dd4eb925bde4d426c6e422582793b260c" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
log = { version = "0.4.17" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
notify = { version = "4.0.17" }
|
||||
@@ -36,9 +40,10 @@ path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix
|
||||
rayon = { version = "1.5.3" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
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"] }
|
||||
@@ -50,7 +55,6 @@ update-informer = { version = "0.5.0", default-features = false, features = ["py
|
||||
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
|
||||
|
||||
474
LICENSE
474
LICENSE
@@ -19,3 +19,477 @@ 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-debugger, 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-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.
|
||||
"""
|
||||
|
||||
- RustPython, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 RustPython Team
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
@@ -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));
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
16
flake8_to_ruff/Cargo.lock
generated
16
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.115"
|
||||
version = "0.0.143"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1265,7 +1265,7 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
[[package]]
|
||||
name = "libcst"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=a13ec97dd4eb925bde4d426c6e422582793b260c#a13ec97dd4eb925bde4d426c6e422582793b260c"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=f2f0b7a487a8725d161fe8b3ed73a6758b21e177#f2f0b7a487a8725d161fe8b3ed73a6758b21e177"
|
||||
dependencies = [
|
||||
"chic",
|
||||
"itertools",
|
||||
@@ -1280,7 +1280,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libcst_derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=a13ec97dd4eb925bde4d426c6e422582793b260c#a13ec97dd4eb925bde4d426c6e422582793b260c"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=f2f0b7a487a8725d161fe8b3ed73a6758b21e177#f2f0b7a487a8725d161fe8b3ed73a6758b21e177"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.115"
|
||||
version = "0.0.143"
|
||||
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=27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb#27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb"
|
||||
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=27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb#27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb"
|
||||
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=27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb#27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb"
|
||||
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=27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb#27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=f885db8c61514f069979861f6b3bd83292086231#f885db8c61514f069979861f6b3bd83292086231"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.115-dev.0"
|
||||
version = "0.0.143-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
@@ -13,6 +13,7 @@ configparser = { version = "3.0.2" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
regex = { version = "1.6.0" }
|
||||
ruff = { path = "..", default-features = false }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
toml = { version = "0.5.9" }
|
||||
|
||||
@@ -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_bugbear, 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,11 +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_bugbear: flake8_bugbear::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() {
|
||||
@@ -105,7 +110,7 @@ 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}"),
|
||||
}
|
||||
@@ -172,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}"),
|
||||
}
|
||||
@@ -185,16 +203,22 @@ pub fn convert(
|
||||
// Deduplicate and sort.
|
||||
options.select = Some(Vec::from_iter(select));
|
||||
options.ignore = Some(Vec::from_iter(ignore));
|
||||
if flake8_annotations != Default::default() {
|
||||
if flake8_annotations != flake8_annotations::settings::Options::default() {
|
||||
options.flake8_annotations = Some(flake8_annotations);
|
||||
}
|
||||
if flake8_bugbear != Default::default() {
|
||||
if flake8_bugbear != flake8_bugbear::settings::Options::default() {
|
||||
options.flake8_bugbear = Some(flake8_bugbear);
|
||||
}
|
||||
if flake8_quotes != Default::default() {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -219,26 +243,31 @@ mod tests {
|
||||
fn it_converts_empty() -> Result<()> {
|
||||
let actual = convert(&HashMap::from([]), None)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
src: None,
|
||||
fix: 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);
|
||||
@@ -253,26 +282,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(100),
|
||||
src: None,
|
||||
fix: 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: 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);
|
||||
@@ -287,26 +321,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(100),
|
||||
src: None,
|
||||
fix: 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: 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);
|
||||
@@ -321,26 +360,31 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
src: None,
|
||||
fix: 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);
|
||||
@@ -355,22 +399,25 @@ mod tests {
|
||||
Some(vec![]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
src: None,
|
||||
fix: 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 {
|
||||
@@ -379,7 +426,9 @@ mod tests {
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
flake8_tidy_imports: None,
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -397,11 +446,16 @@ mod tests {
|
||||
Some(vec![Plugin::Flake8Docstrings]),
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
src: None,
|
||||
fix: 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,
|
||||
@@ -442,16 +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);
|
||||
@@ -466,23 +520,26 @@ mod tests {
|
||||
None,
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: None,
|
||||
src: None,
|
||||
fix: 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 {
|
||||
@@ -491,7 +548,9 @@ mod tests {
|
||||
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)
|
||||
|
||||
@@ -10,10 +10,14 @@ pub enum Plugin {
|
||||
Flake8Bugbear,
|
||||
Flake8Builtins,
|
||||
Flake8Comprehensions,
|
||||
Flake8Debugger,
|
||||
Flake8Docstrings,
|
||||
Flake8TidyImports,
|
||||
Flake8Print,
|
||||
Flake8Quotes,
|
||||
Flake8Annotations,
|
||||
McCabe,
|
||||
Flake8BlindExcept,
|
||||
PEP8Naming,
|
||||
Pyupgrade,
|
||||
}
|
||||
@@ -27,10 +31,14 @@ impl FromStr for Plugin {
|
||||
"flake8-bugbear" => Ok(Plugin::Flake8Bugbear),
|
||||
"flake8-builtins" => Ok(Plugin::Flake8Builtins),
|
||||
"flake8-comprehensions" => Ok(Plugin::Flake8Comprehensions),
|
||||
"flake8-debugger" => Ok(Plugin::Flake8Debugger),
|
||||
"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)),
|
||||
@@ -44,11 +52,15 @@ impl Plugin {
|
||||
Plugin::Flake8Bandit => CheckCodePrefix::S,
|
||||
Plugin::Flake8Bugbear => CheckCodePrefix::B,
|
||||
Plugin::Flake8Builtins => CheckCodePrefix::A,
|
||||
Plugin::Flake8Comprehensions => CheckCodePrefix::C,
|
||||
Plugin::Flake8Comprehensions => CheckCodePrefix::C4,
|
||||
Plugin::Flake8Debugger => CheckCodePrefix::T1,
|
||||
Plugin::Flake8Docstrings => CheckCodePrefix::D,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T,
|
||||
Plugin::Flake8TidyImports => CheckCodePrefix::I25,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T2,
|
||||
Plugin::Flake8Quotes => CheckCodePrefix::Q,
|
||||
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
|
||||
Plugin::Flake8BlindExcept => CheckCodePrefix::BLE,
|
||||
Plugin::McCabe => CheckCodePrefix::C9,
|
||||
Plugin::PEP8Naming => CheckCodePrefix::N,
|
||||
Plugin::Pyupgrade => CheckCodePrefix::U,
|
||||
}
|
||||
@@ -59,7 +71,8 @@ impl Plugin {
|
||||
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::Flake8Debugger => vec![CheckCodePrefix::T1],
|
||||
Plugin::Flake8Docstrings => {
|
||||
// Use the user-provided docstring.
|
||||
for key in ["docstring-convention", "docstring_convention"] {
|
||||
@@ -76,9 +89,12 @@ impl Plugin {
|
||||
// Default to PEP8.
|
||||
DocstringConvention::PEP8.select()
|
||||
}
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T],
|
||||
Plugin::Flake8TidyImports => vec![CheckCodePrefix::I25],
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T2],
|
||||
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],
|
||||
}
|
||||
@@ -315,6 +331,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);
|
||||
@@ -341,10 +368,13 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
Plugin::Flake8Bugbear,
|
||||
Plugin::Flake8Builtins,
|
||||
Plugin::Flake8Comprehensions,
|
||||
Plugin::Flake8Debugger,
|
||||
Plugin::Flake8Docstrings,
|
||||
Plugin::Flake8TidyImports,
|
||||
Plugin::Flake8Print,
|
||||
Plugin::Flake8Quotes,
|
||||
Plugin::Flake8Annotations,
|
||||
Plugin::Flake8BlindExcept,
|
||||
Plugin::PEP8Naming,
|
||||
Plugin::Pyupgrade,
|
||||
]
|
||||
|
||||
@@ -25,12 +25,11 @@ 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]
|
||||
|
||||
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
|
||||
|
||||
1
resources/test/fixtures/B009_B010.py
vendored
1
resources/test/fixtures/B009_B010.py
vendored
@@ -34,3 +34,4 @@ 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
|
||||
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
|
||||
82
resources/test/fixtures/B023.py
vendored
Normal file
82
resources/test/fixtures/B023.py
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
Should emit:
|
||||
B023 - on lines 12, 13, 16, 28, 29, 30, 31, 40, 42, 50, 51, 52, 53, 61, 68.
|
||||
"""
|
||||
|
||||
functions = []
|
||||
z = 0
|
||||
|
||||
for x in range(3):
|
||||
y = x + 1
|
||||
# Subject to late-binding problems
|
||||
functions.append(lambda: x)
|
||||
functions.append(lambda: y) # not just the loop var
|
||||
|
||||
def f_bad_1():
|
||||
return x
|
||||
|
||||
# Actually OK
|
||||
functions.append(lambda x: x * 2)
|
||||
functions.append(lambda x=x: x)
|
||||
functions.append(lambda: z) # OK because not assigned in the loop
|
||||
|
||||
def f_ok_1(x):
|
||||
return x * 2
|
||||
|
||||
|
||||
def check_inside_functions_too():
|
||||
ls = [lambda: x for x in range(2)]
|
||||
st = {lambda: x for x in range(2)}
|
||||
gn = (lambda: x for x in range(2))
|
||||
dt = {x: lambda: x for x in range(2)}
|
||||
|
||||
|
||||
async def pointless_async_iterable():
|
||||
yield 1
|
||||
|
||||
|
||||
async def container_for_problems():
|
||||
async for x in pointless_async_iterable():
|
||||
functions.append(lambda: x)
|
||||
|
||||
[lambda: x async for x in pointless_async_iterable()]
|
||||
|
||||
|
||||
a = 10
|
||||
b = 0
|
||||
while True:
|
||||
a = a_ = a - 1
|
||||
b += 1
|
||||
functions.append(lambda: a)
|
||||
functions.append(lambda: a_)
|
||||
functions.append(lambda: b)
|
||||
functions.append(lambda: c) # not a name error because of late binding!
|
||||
c: bool = a > 3
|
||||
if not c:
|
||||
break
|
||||
|
||||
# Nested loops should not duplicate reports
|
||||
for j in range(2):
|
||||
for k in range(3):
|
||||
lambda: j * k
|
||||
|
||||
|
||||
for j, k, l in [(1, 2, 3)]:
|
||||
|
||||
def f():
|
||||
j = None # OK because it's an assignment
|
||||
[l for k in range(2)] # error for l, not for k
|
||||
|
||||
assert a and functions
|
||||
|
||||
a.attribute = 1 # modifying an attribute doesn't make it a loop variable
|
||||
functions[0] = lambda: None # same for an element
|
||||
|
||||
for var in range(2):
|
||||
|
||||
def explicit_capture(captured=var):
|
||||
return captured
|
||||
|
||||
|
||||
for i in range(3):
|
||||
lambda: f"{i}"
|
||||
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
|
||||
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/B904.py
vendored
Normal file
55
resources/test/fixtures/B904.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Should emit:
|
||||
B904 - on lines 10, 11 and 16
|
||||
"""
|
||||
|
||||
try:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
if "abc":
|
||||
raise TypeError
|
||||
raise UserWarning
|
||||
except AssertionError:
|
||||
raise # Bare `raise` should not be an error
|
||||
except Exception as err:
|
||||
assert err
|
||||
raise Exception("No cause here...")
|
||||
except BaseException as base_err:
|
||||
# Might use this instead of bare raise with the `.with_traceback()` method
|
||||
raise base_err
|
||||
finally:
|
||||
raise Exception("Nothing to chain from, so no warning here")
|
||||
|
||||
try:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
# should not emit, since we are not raising something
|
||||
def proxy():
|
||||
raise NameError
|
||||
|
||||
|
||||
try:
|
||||
from preferred_library import Thing
|
||||
except ImportError:
|
||||
try:
|
||||
from fallback_library import Thing
|
||||
except ImportError:
|
||||
|
||||
class Thing:
|
||||
def __getattr__(self, name):
|
||||
# same as the case above, should not emit.
|
||||
raise AttributeError
|
||||
|
||||
|
||||
try:
|
||||
from preferred_library import Thing
|
||||
except ImportError:
|
||||
try:
|
||||
from fallback_library import Thing
|
||||
except ImportError:
|
||||
|
||||
def context_switch():
|
||||
try:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
raise
|
||||
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
|
||||
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())
|
||||
41
resources/test/fixtures/D.py
vendored
41
resources/test/fixtures/D.py
vendored
@@ -3,6 +3,7 @@ from functools import wraps
|
||||
import os
|
||||
from .expected import Expectation
|
||||
from typing import overload
|
||||
from typing_extensions import override
|
||||
|
||||
|
||||
expectation = Expectation()
|
||||
@@ -42,9 +43,13 @@ class class_:
|
||||
"D418: Function/ Method decorated with @overload"
|
||||
" shouldn't contain a docstring")
|
||||
|
||||
@override
|
||||
def overridden_method(a):
|
||||
return str(a)
|
||||
|
||||
@property
|
||||
def foo(self):
|
||||
"""The foo of the thing, which isn't in imperitive mood."""
|
||||
"""The foo of the thing, which isn't in imperative mood."""
|
||||
return "hello"
|
||||
|
||||
@expect('D102: Missing docstring in public method')
|
||||
@@ -532,3 +537,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
|
||||
|
||||
5
resources/test/fixtures/E501.py
vendored
5
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
|
||||
|
||||
@@ -49,3 +49,6 @@ sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labor
|
||||
sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
""", # noqa: E501
|
||||
}
|
||||
|
||||
# OK
|
||||
# A very long URL: https://loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong.url.com
|
||||
|
||||
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"
|
||||
|
||||
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
|
||||
13
resources/test/fixtures/F502.py
vendored
Normal file
13
resources/test/fixtures/F502.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
dog = {"bob": "bob"}
|
||||
|
||||
"%(bob)s" % dog
|
||||
"%(bob)s" % {"bob": "bob"}
|
||||
"%(bob)s" % {**{"bob": "bob"}}
|
||||
"%(bob)s" % ["bob"] # F202
|
||||
"%(bob)s" % ("bob",) # F202
|
||||
"%(bob)s" % {"bob"} # F202
|
||||
"%(bob)s" % [*["bob"]] # F202
|
||||
"%(bob)s" % {"bob": "bob" for _ in range(1)}
|
||||
"%(bob)s" % ["bob" for _ in range(1)] # F202
|
||||
"%(bob)s" % ("bob" for _ in range(1)) # F202
|
||||
"%(bob)s" % {"bob" for _ in range(1)} # F202
|
||||
26
resources/test/fixtures/F503.py
vendored
Normal file
26
resources/test/fixtures/F503.py
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
dog = {"bob": "bob"}
|
||||
|
||||
# Single placeholder always fine
|
||||
"%s" % dog
|
||||
"%s" % {"bob": "bob"}
|
||||
"%s" % {**{"bob": "bob"}}
|
||||
"%s" % ["bob"]
|
||||
"%s" % ("bob",)
|
||||
"%s" % {"bob"}
|
||||
"%s" % [*["bob"]]
|
||||
"%s" % {"bob": "bob" for _ in range(1)}
|
||||
"%s" % ["bob" for _ in range(1)]
|
||||
"%s" % ("bob" for _ in range(1))
|
||||
"%s" % {"bob" for _ in range(1)}
|
||||
# Multiple placeholders
|
||||
"%s %s" % dog
|
||||
"%s %s" % {"bob": "bob"} # F503
|
||||
"%s %s" % {**{"bob": "bob"}} # F503
|
||||
"%s %s" % ["bob"]
|
||||
"%s %s" % ("bob",)
|
||||
"%s %s" % {"bob"}
|
||||
"%s %s" % [*["bob"]]
|
||||
"%s %s" % {"bob": "bob" for _ in range(1)} # F503
|
||||
"%s %s" % ["bob" for _ in range(1)]
|
||||
"%s %s" % ("bob" for _ in range(1))
|
||||
"%s %s" % {"bob" for _ in range(1)}
|
||||
6
resources/test/fixtures/F504.py
vendored
Normal file
6
resources/test/fixtures/F504.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Ruff has no way of knowing if the following are F505s
|
||||
a = "wrong"
|
||||
"%(a)s %(c)s" % {a: "?", "b": "!"} # F504 ("b" not used)
|
||||
|
||||
hidden = {"a": "!"}
|
||||
"%(a)s %(c)s" % {"x": 1, **hidden} # Ok (cannot see through splat)
|
||||
25
resources/test/fixtures/F50x.py
vendored
Normal file
25
resources/test/fixtures/F50x.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
'%(foo)' % {'foo': 'bar'} # F501
|
||||
'%s %(foo)s' % {'foo': 'bar'} # F506
|
||||
'%(foo)s %s' % {'foo': 'bar'} # F506
|
||||
'%j' % (1,) # F509
|
||||
'%s %s' % (1,) # F507
|
||||
'%s %s' % (1, 2, 3) # F507
|
||||
'%(bar)s' % {} # F505
|
||||
'%(bar)s' % {'bar': 1, 'baz': 2} # F504
|
||||
'%(bar)s' % (1, 2, 3) # F502
|
||||
'%s %s' % {'k': 'v'} # F503
|
||||
'%(bar)*s' % {'bar': 'baz'} # F506, F508
|
||||
|
||||
# ok: single %s with mapping
|
||||
'%s' % {'foo': 'bar', 'baz': 'womp'}
|
||||
# ok: %% should not count towards placeholder count
|
||||
'%% %s %% %s' % (1, 2)
|
||||
# ok: * consumes one positional argument
|
||||
'%.*f' % (2, 1.1234)
|
||||
'%*.*f' % (5, 2, 3.1234)
|
||||
# ok *args and **kwargs
|
||||
a = []
|
||||
'%s %s' % [*a]
|
||||
'%s %s' % (*a,)
|
||||
k = {}
|
||||
'%(k)s' % {**k}
|
||||
21
resources/test/fixtures/F521.py
vendored
Normal file
21
resources/test/fixtures/F521.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
"{".format(1)
|
||||
"}".format(1)
|
||||
"{foo[}".format(foo=1)
|
||||
# too much string recursion (placeholder-in-placeholder)
|
||||
"{:{:{}}}".format(1, 2, 3)
|
||||
# ruff picks these issues up, but flake8 doesn't
|
||||
"{foo[]}".format(foo={"": 1})
|
||||
"{foo..}".format(foo=1)
|
||||
"{foo..bar}".format(foo=1)
|
||||
|
||||
# The following are all "good" uses of .format
|
||||
"{.__class__}".format("")
|
||||
"{foo[bar]}".format(foo={"bar": "barv"})
|
||||
"{[bar]}".format({"bar": "barv"})
|
||||
"{:{}} {}".format(1, 15, 2)
|
||||
"{:2}".format(1)
|
||||
"{foo}-{}".format(1, foo=2)
|
||||
a = ()
|
||||
"{}".format(*a)
|
||||
k = {}
|
||||
"{foo}".format(**k)
|
||||
4
resources/test/fixtures/F522.py
vendored
Normal file
4
resources/test/fixtures/F522.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
"{}".format(1, bar=2) # F522
|
||||
"{bar}{}".format(1, bar=2, spam=3) # F522
|
||||
"{bar:{spam}}".format(bar=2, spam=3) # No issues
|
||||
"{bar:{spam}}".format(bar=2, spam=3, eggs=4, ham=5) # F522
|
||||
12
resources/test/fixtures/F523.py
vendored
Normal file
12
resources/test/fixtures/F523.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# With indexes
|
||||
"{0}".format(1, 2) # F523
|
||||
"{1}".format(1, 2, 3) # F523
|
||||
"{1:{0}}".format(1, 2) # No issues
|
||||
"{1:{0}}".format(1, 2, 3) # F523
|
||||
"{0}{2}".format(1, 2) # F523, # F524
|
||||
|
||||
# With no indexes
|
||||
"{}".format(1, 2) # F523
|
||||
"{}".format(1, 2, 3) # F523
|
||||
"{:{}}".format(1, 2) # No issues
|
||||
"{:{}}".format(1, 2, 3) # F523
|
||||
6
resources/test/fixtures/F524.py
vendored
Normal file
6
resources/test/fixtures/F524.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
"{} {}".format(1) # F524
|
||||
"{2}".format() # F524
|
||||
"{bar}".format() # F524
|
||||
"{0} {bar}".format(1) # F524
|
||||
"{0} {bar}".format() # F524
|
||||
"{bar} {0}".format() # F524
|
||||
2
resources/test/fixtures/F525.py
vendored
Normal file
2
resources/test/fixtures/F525.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"{} {1}".format(1, 2) # F525
|
||||
"{0} {}".format(1, 2) # F523, F525
|
||||
10
resources/test/fixtures/F821_3.py
vendored
10
resources/test/fixtures/F821_3.py
vendored
@@ -12,3 +12,13 @@ x: dict["key", "value"]
|
||||
|
||||
# OK
|
||||
x: dict[str, str]
|
||||
|
||||
# OK
|
||||
def unimportant(name):
|
||||
pass
|
||||
|
||||
|
||||
def dang(dict, set, list):
|
||||
unimportant(name=dict["name"])
|
||||
unimportant(name=set["name"])
|
||||
unimportant(name=list["name"])
|
||||
|
||||
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()
|
||||
30
resources/test/fixtures/F841.py
vendored
30
resources/test/fixtures/F841.py
vendored
@@ -35,3 +35,33 @@ 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])
|
||||
|
||||
|
||||
def f7():
|
||||
def connect():
|
||||
return None, None
|
||||
|
||||
with connect() as (connection, cursor):
|
||||
cursor.execute("SELECT * FROM users")
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
14
resources/test/fixtures/T100.py
vendored
Normal file
14
resources/test/fixtures/T100.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
breakpoint()
|
||||
|
||||
|
||||
import pdb
|
||||
from builtins import breakpoint
|
||||
from pdb import set_trace as st
|
||||
from celery.contrib.rdb import set_trace
|
||||
from celery.contrib import rdb
|
||||
import celery.contrib.rdb
|
||||
|
||||
|
||||
breakpoint()
|
||||
st()
|
||||
set_trace()
|
||||
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:
|
||||
...
|
||||
|
||||
2
resources/test/fixtures/U009_0.py
vendored
2
resources/test/fixtures/U009_0.py
vendored
@@ -1,3 +1,3 @@
|
||||
# coding=utf8
|
||||
|
||||
print('Hello world')
|
||||
print("Hello world")
|
||||
|
||||
3
resources/test/fixtures/U009_4.py
vendored
Normal file
3
resources/test/fixtures/U009_4.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# coding=utf8 # noqa: U009
|
||||
|
||||
print("Hello world")
|
||||
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"],
|
||||
)
|
||||
80
resources/test/fixtures/U015.py
vendored
Normal file
80
resources/test/fixtures/U015.py
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
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
|
||||
|
||||
open("foo", mode="U")
|
||||
open(name="foo", mode="U")
|
||||
open(mode="U", name="foo")
|
||||
|
||||
with open("foo", mode="U") as f:
|
||||
pass
|
||||
with open(name="foo", mode="U") as f:
|
||||
pass
|
||||
with open(mode="U", name="foo") as f:
|
||||
pass
|
||||
|
||||
open("foo", mode="Ub")
|
||||
open(name="foo", mode="Ub")
|
||||
open(mode="Ub", name="foo")
|
||||
|
||||
with open("foo", mode="Ub") as f:
|
||||
pass
|
||||
with open(name="foo", mode="Ub") as f:
|
||||
pass
|
||||
with open(mode="Ub", name="foo") as f:
|
||||
pass
|
||||
|
||||
open(file="foo", mode='U', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None, mode='U')
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, mode='U', newline=None, closefd=True, opener=None)
|
||||
open(mode='U', file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
|
||||
open(file="foo", mode='Ub', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None, mode='Ub')
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, mode='Ub', newline=None, closefd=True, opener=None)
|
||||
open(mode='Ub', file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
|
||||
open = 1
|
||||
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")
|
||||
3
resources/test/fixtures/YTT101.py
vendored
3
resources/test/fixtures/YTT101.py
vendored
@@ -5,9 +5,8 @@ print(sys.version)
|
||||
|
||||
print(sys.version[:3])
|
||||
print(version[:3])
|
||||
|
||||
# ignore from imports with aliases, patches welcome
|
||||
print(v[:3])
|
||||
|
||||
# the tool is timid and only flags certain numeric slices
|
||||
i = 3
|
||||
print(sys.version[:i])
|
||||
|
||||
@@ -44,7 +44,7 @@ expectation.expected.add((
|
||||
@expect("D407: Missing dashed underline after section ('Returns')",
|
||||
arg_count=3)
|
||||
@expect("D413: Missing blank line after last section ('Raises')", arg_count=3)
|
||||
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
|
||||
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None, **kwargs):
|
||||
"""Fetches rows from a Bigtable.
|
||||
|
||||
Retrieves rows pertaining to the given keys from the Table instance
|
||||
@@ -57,6 +57,7 @@ def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
|
||||
to fetch.
|
||||
other_silly_variable: Another optional variable, that has a much
|
||||
longer name than the other args, and which does nothing.
|
||||
**kwargs: More keyword arguments.
|
||||
|
||||
Returns:
|
||||
A dict mapping keys to the corresponding table row data
|
||||
|
||||
@@ -73,7 +73,7 @@ expectation.expected.add((
|
||||
"(found 'A')", arg_count=3)
|
||||
@expect("D413: Missing blank line after last section ('Examples')",
|
||||
arg_count=3)
|
||||
def foo(var1, var2, long_var_name='hi'):
|
||||
def foo(var1, var2, long_var_name='hi', **kwargs):
|
||||
r"""A one-line summary that does not use variable names.
|
||||
|
||||
Several sentences providing an extended description. Refer to
|
||||
@@ -91,6 +91,8 @@ def foo(var1, var2, long_var_name='hi'):
|
||||
detail, e.g. ``(N,) ndarray`` or ``array_like``.
|
||||
long_var_name : {'hi', 'ho'}, optional
|
||||
Choices in brackets, default first when optional.
|
||||
**kwargs : int
|
||||
More keyword arguments.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
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
|
||||
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/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.
|
||||
4
resources/test/fixtures/isort/order_relative_imports_by_level.py
vendored
Normal file
4
resources/test/fixtures/isort/order_relative_imports_by_level.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from .a import a
|
||||
from ..a import a
|
||||
from ..b import a
|
||||
from .b import a
|
||||
11
resources/test/fixtures/isort/preserve_comment_order.py
vendored
Normal file
11
resources/test/fixtures/isort/preserve_comment_order.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import io
|
||||
# Old MacDonald had a farm,
|
||||
# EIEIO
|
||||
# And on his farm he had a cow,
|
||||
# EIEIO
|
||||
# With a moo-moo here and a moo-moo there
|
||||
# Here a moo, there a moo, everywhere moo-moo
|
||||
# Old MacDonald had a farm,
|
||||
# EIEIO
|
||||
from errno import EIO
|
||||
import abc
|
||||
26
resources/test/fixtures/isort/sort_similar_imports.py
vendored
Normal file
26
resources/test/fixtures/isort/sort_similar_imports.py
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
from a import b
|
||||
from a import BAD as DEF
|
||||
from a import B
|
||||
from a import Boo as DEF
|
||||
from a import B as Abc
|
||||
from a import B as A
|
||||
from a import B as DEF
|
||||
from a import b as a
|
||||
from a import b as x
|
||||
from a import b as c
|
||||
from b import c
|
||||
from a import b as d
|
||||
from a import b as y
|
||||
from b import C
|
||||
from b import c as d
|
||||
|
||||
import A
|
||||
import a
|
||||
import b
|
||||
import B
|
||||
|
||||
import x as y
|
||||
import x as A
|
||||
import x as Y
|
||||
import x
|
||||
import x as a
|
||||
2
resources/test/fixtures/isort/type_comments.py
vendored
Normal file
2
resources/test/fixtures/isort/type_comments.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import A # type: ignore
|
||||
from B import C # type: ignore
|
||||
7
resources/test/fixtures/pyproject.toml
vendored
7
resources/test/fixtures/pyproject.toml
vendored
@@ -16,6 +16,9 @@ multiline-quotes = "double"
|
||||
docstring-quotes = "double"
|
||||
avoid-escape = true
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.pep8-naming]
|
||||
ignore-names = [
|
||||
"setUp",
|
||||
@@ -33,7 +36,11 @@ ignore-names = [
|
||||
]
|
||||
classmethod-decorators = [
|
||||
"classmethod",
|
||||
"pydantic.validator",
|
||||
]
|
||||
staticmethod-decorators = [
|
||||
"staticmethod",
|
||||
]
|
||||
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
ban-relative-imports = "parents"
|
||||
|
||||
@@ -4,4 +4,4 @@ import sysconfig
|
||||
|
||||
if __name__ == "__main__":
|
||||
ruff = os.path.join(sysconfig.get_path("scripts"), "ruff")
|
||||
os.spawnv(os.P_WAIT, ruff, [ruff, *sys.argv[1:]])
|
||||
sys.exit(os.spawnv(os.P_WAIT, ruff, [ruff, *sys.argv[1:]]))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.115"
|
||||
version = "0.0.143"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -8,10 +8,10 @@ anyhow = { version = "1.0.66" }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
codegen = { version = "0.2.0" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "a13ec97dd4eb925bde4d426c6e422582793b260c" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
ruff = { path = ".." }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "27bf82a2251d7e6ac6cd75e6ad51be12a53d84bb" }
|
||||
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" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
|
||||
@@ -24,7 +24,7 @@ pub struct Cli {
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
// Build up a map from prefix to matching CheckCodes.
|
||||
let mut prefix_to_codes: BTreeMap<String, BTreeSet<CheckCode>> = Default::default();
|
||||
let mut prefix_to_codes: BTreeMap<String, BTreeSet<CheckCode>> = BTreeMap::default();
|
||||
for check_code in CheckCode::iter() {
|
||||
let as_ref: String = check_code.as_ref().to_string();
|
||||
let prefix_len = as_ref
|
||||
@@ -77,6 +77,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
.arg_ref_self()
|
||||
.ret(Type::new("Vec<CheckCode>"))
|
||||
.vis("pub")
|
||||
.line("#[allow(clippy::match_same_arms)]")
|
||||
.line("match self {");
|
||||
for (prefix, codes) in &prefix_to_codes {
|
||||
gen = gen.line(format!(
|
||||
@@ -96,6 +97,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
.arg_ref_self()
|
||||
.ret(Type::new("PrefixSpecificity"))
|
||||
.vis("pub")
|
||||
.line("#[allow(clippy::match_same_arms)]")
|
||||
.line("match self {");
|
||||
for prefix in prefix_to_codes.keys() {
|
||||
let num_numeric = prefix.chars().filter(|char| char.is_numeric()).count();
|
||||
@@ -104,7 +106,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
2 => "Tens",
|
||||
1 => "Hundreds",
|
||||
0 => "Category",
|
||||
_ => panic!("Invalid prefix: {}", prefix),
|
||||
_ => panic!("Invalid prefix: {prefix}"),
|
||||
};
|
||||
gen = gen.line(format!(
|
||||
"CheckCodePrefix::{prefix} => PrefixSpecificity::{},",
|
||||
@@ -115,7 +117,8 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
|
||||
// Construct the output contents.
|
||||
let mut output = String::new();
|
||||
output.push_str("//! File automatically generated by examples/generate_check_code_prefix.rs.");
|
||||
output
|
||||
.push_str("//! File automatically generated by `examples/generate_check_code_prefix.rs`.");
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
output.push_str("use serde::{{Serialize, Deserialize}};");
|
||||
@@ -127,13 +130,28 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
output.push_str(&scope.to_string());
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
// Add the list of output categories (not generated).
|
||||
output.push_str("pub const CATEGORIES: &[CheckCodePrefix] = &[");
|
||||
output.push('\n');
|
||||
for prefix in prefix_to_codes.keys() {
|
||||
if prefix.chars().all(char::is_alphabetic) {
|
||||
output.push_str(&format!("CheckCodePrefix::{prefix},"));
|
||||
output.push('\n');
|
||||
}
|
||||
}
|
||||
output.push_str("];");
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
// Write the output to `src/checks_gen.rs` (or stdout).
|
||||
if cli.dry_run {
|
||||
println!("{}", output);
|
||||
println!("{output}");
|
||||
} else {
|
||||
let mut f = OpenOptions::new().write(true).truncate(true).open(FILE)?;
|
||||
write!(f, "{}", output)?;
|
||||
write!(f, "{output}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
}
|
||||
|
||||
if cli.dry_run {
|
||||
print!("{}", output);
|
||||
print!("{output}");
|
||||
} else {
|
||||
// Read the existing file.
|
||||
let file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
@@ -84,9 +84,9 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
|
||||
// Write the prefix, new contents, and suffix.
|
||||
let mut f = OpenOptions::new().write(true).truncate(true).open(&file)?;
|
||||
write!(f, "{}\n\n", prefix)?;
|
||||
write!(f, "{}", output)?;
|
||||
write!(f, "{}", suffix)?;
|
||||
write!(f, "{prefix}\n\n")?;
|
||||
write!(f, "{output}")?;
|
||||
write!(f, "{suffix}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
let contents = fs::read_to_string(&cli.file)?;
|
||||
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
||||
let mut generator = SourceGenerator::new();
|
||||
generator.unparse_suite(&python_ast)?;
|
||||
generator.unparse_suite(&python_ast);
|
||||
println!("{}", generator.generate()?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
#![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 generate_check_code_prefix;
|
||||
pub mod generate_rules_table;
|
||||
pub mod generate_source_code;
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
#![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 anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use ruff_dev::{
|
||||
|
||||
@@ -17,6 +17,6 @@ pub struct Cli {
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
let contents = fs::read_to_string(&cli.file)?;
|
||||
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
||||
println!("{:#?}", python_ast);
|
||||
println!("{python_ast:#?}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Print the LibCST CST for a given Python file.
|
||||
//! Print the `LibCST` CST for a given Python file.
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
@@ -17,7 +17,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
let contents = fs::read_to_string(&cli.file)?;
|
||||
match libcst_native::parse_module(&contents, None) {
|
||||
Ok(python_cst) => {
|
||||
println!("{:#?}", python_cst);
|
||||
println!("{python_cst:#?}");
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Err(anyhow::anyhow!("Failed to parse CST")),
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct Cli {
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
let contents = fs::read_to_string(&cli.file)?;
|
||||
for (_, tok, _) in lexer::make_tokenizer(&contents).flatten() {
|
||||
println!("{:#?}", tok);
|
||||
println!("{tok:#?}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user