Compare commits
313 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4c0a41b00 | ||
|
|
8702b5a40a | ||
|
|
bab818e801 | ||
|
|
a3aa841fc9 | ||
|
|
fdd894145b | ||
|
|
85f67b2ee3 | ||
|
|
e9c6f16c56 | ||
|
|
d3b18345c5 | ||
|
|
0e4d174551 | ||
|
|
73efbeb581 | ||
|
|
2fb312bb2b | ||
|
|
e8e66f3824 | ||
|
|
a8d080c825 | ||
|
|
ddd541b198 | ||
|
|
3090aec97d | ||
|
|
14c6419bc1 | ||
|
|
3bc29d6c0c | ||
|
|
67c5086aba | ||
|
|
cd82b83f89 | ||
|
|
39fb2cc732 | ||
|
|
9c732c7946 | ||
|
|
2332ea5753 | ||
|
|
6b1062ccc3 | ||
|
|
39fa38cb35 | ||
|
|
ddf7de7e86 | ||
|
|
e5101e8eac | ||
|
|
d9c3f8e249 | ||
|
|
7e0d018b35 | ||
|
|
4b05ca1198 | ||
|
|
f0465bf106 | ||
|
|
8134ec25f0 | ||
|
|
6049aabe27 | ||
|
|
badade3ccc | ||
|
|
fa26860296 | ||
|
|
140e0acf54 | ||
|
|
c711db11ce | ||
|
|
1fe6954150 | ||
|
|
2414469ac3 | ||
|
|
838ba1ca3d | ||
|
|
8f3f8d3e0b | ||
|
|
8ba9eb83af | ||
|
|
2c6efc2f5f | ||
|
|
d6930ca991 | ||
|
|
f70c286e6a | ||
|
|
dcff515ad8 | ||
|
|
b9e387013f | ||
|
|
a69451ff46 | ||
|
|
01b372a75c | ||
|
|
cd2e7fa72a | ||
|
|
fdf0b999cd | ||
|
|
45b5fa573f | ||
|
|
a0258f2205 | ||
|
|
0a68636de3 | ||
|
|
2f53781a77 | ||
|
|
7e7be05ddf | ||
|
|
f5afa8198c | ||
|
|
eeabfd6d18 | ||
|
|
490301f9fe | ||
|
|
f5be3d8e5b | ||
|
|
7617519b4f | ||
|
|
bc7ddd8f3a | ||
|
|
e6bb5cddcf | ||
|
|
dcedd5cd9d | ||
|
|
606b6ac3df | ||
|
|
ebda9b31d9 | ||
|
|
52f6663089 | ||
|
|
a6176d2c70 | ||
|
|
1d165f7e9d | ||
|
|
e96092291d | ||
|
|
67076b2dcb | ||
|
|
7e3ba7f32a | ||
|
|
09dbd2029c | ||
|
|
1380bd94da | ||
|
|
c10a4535b9 | ||
|
|
97802e7466 | ||
|
|
4fd4a65718 | ||
|
|
d78c614764 | ||
|
|
3f3dd7af99 | ||
|
|
871b92a385 | ||
|
|
9158f13ee6 | ||
|
|
72e0ffc1ac | ||
|
|
ffcf0618c7 | ||
|
|
1ccef5150d | ||
|
|
6a52577630 | ||
|
|
3c2f41b615 | ||
|
|
b76b4b6016 | ||
|
|
bbadbb5de5 | ||
|
|
ba6370e5d0 | ||
|
|
be6e00ef6e | ||
|
|
865205d992 | ||
|
|
572adf7994 | ||
|
|
3b26bf84f5 | ||
|
|
f4f88308ae | ||
|
|
ea3d3a655d | ||
|
|
fd34797d0f | ||
|
|
6532455672 | ||
|
|
257c571c43 | ||
|
|
ccdee55e6e | ||
|
|
6d6d7abf70 | ||
|
|
0096938789 | ||
|
|
853d8354cb | ||
|
|
5f64d2346f | ||
|
|
ddbe5a1243 | ||
|
|
04097d194c | ||
|
|
a2b8487ae3 | ||
|
|
8969ad5879 | ||
|
|
bfa1c28c00 | ||
|
|
cf7aa26aa4 | ||
|
|
d66ce76691 | ||
|
|
b8bb9e8b92 | ||
|
|
5e46dcbf21 | ||
|
|
045449ab12 | ||
|
|
d5ff8d7c43 | ||
|
|
d92fb11e80 | ||
|
|
3d947196f8 | ||
|
|
e846f2688b | ||
|
|
7b91a162c6 | ||
|
|
8c2cfade90 | ||
|
|
a435c0df4b | ||
|
|
48e1852893 | ||
|
|
03f141f53d | ||
|
|
8dea47afc1 | ||
|
|
d3b71f1e04 | ||
|
|
04e8e74499 | ||
|
|
318653c427 | ||
|
|
f08fd5cbf0 | ||
|
|
99a755f936 | ||
|
|
e7dfb35778 | ||
|
|
085fd37209 | ||
|
|
83536cf87b | ||
|
|
9366eb919d | ||
|
|
8be51942dd | ||
|
|
d365dab904 | ||
|
|
f23851130a | ||
|
|
efdf383f5e | ||
|
|
61f21a6513 | ||
|
|
43d6aa9173 | ||
|
|
c54e48dce5 | ||
|
|
b913e99bde | ||
|
|
4ac506526b | ||
|
|
cd41de2588 | ||
|
|
3344d367f5 | ||
|
|
d7a369e7dc | ||
|
|
1b1788c8ad | ||
|
|
4d5a339d9e | ||
|
|
0801f14046 | ||
|
|
edaf891042 | ||
|
|
3beff29026 | ||
|
|
5ac2c7d293 | ||
|
|
e66fdb83d0 | ||
|
|
a95bafefb0 | ||
|
|
539af34f58 | ||
|
|
983bb31577 | ||
|
|
b98b604071 | ||
|
|
cd27b39aff | ||
|
|
a9fc648faf | ||
|
|
c1f0661225 | ||
|
|
2c91412321 | ||
|
|
11e1380df4 | ||
|
|
e93f378635 | ||
|
|
2124feb0e7 | ||
|
|
c0e7269b07 | ||
|
|
c2921e957b | ||
|
|
93cfce674a | ||
|
|
b71cc3789f | ||
|
|
717128112d | ||
|
|
e9e194ab32 | ||
|
|
890e630c41 | ||
|
|
d78287540d | ||
|
|
494e807315 | ||
|
|
6db1a32eb9 | ||
|
|
bb2cbf1f25 | ||
|
|
badfdab61a | ||
|
|
59d40f9f81 | ||
|
|
37aae666c7 | ||
|
|
460023a959 | ||
|
|
d0e3ca29d9 | ||
|
|
ccfc78e2d5 | ||
|
|
b14358fbfe | ||
|
|
ac600bb3da | ||
|
|
8cb76f85eb | ||
|
|
56c45013c2 | ||
|
|
a4ce746892 | ||
|
|
2d6d51f3a1 | ||
|
|
814731364a | ||
|
|
8c97e7922b | ||
|
|
a32617911a | ||
|
|
64b7280eb8 | ||
|
|
8d64747d34 | ||
|
|
2115d99c43 | ||
|
|
39ed75f643 | ||
|
|
8f61eae1e7 | ||
|
|
f0f4bf2929 | ||
|
|
03144b2fad | ||
|
|
0172cc51a7 | ||
|
|
12d64a223b | ||
|
|
432ea6f2e2 | ||
|
|
b34804ceb5 | ||
|
|
ee6d8f7467 | ||
|
|
089b64e9c1 | ||
|
|
3e81403fbe | ||
|
|
3c9f5e2fdc | ||
|
|
17db2e2a62 | ||
|
|
e04ef42334 | ||
|
|
f3e6ddda62 | ||
|
|
cab65b25da | ||
|
|
ee91598835 | ||
|
|
ab65eaea7f | ||
|
|
19d8913e32 | ||
|
|
b9c06b48e1 | ||
|
|
7266eb0d69 | ||
|
|
4df7bc0bcd | ||
|
|
464a0ff483 | ||
|
|
fd7ccb4c9e | ||
|
|
ae6f38344a | ||
|
|
bbf658d4c5 | ||
|
|
1f3b0fd602 | ||
|
|
37483f3ac9 | ||
|
|
4d3a1e0581 | ||
|
|
9e5f348a17 | ||
|
|
5e91211e6d | ||
|
|
df77595426 | ||
|
|
407af6e0ae | ||
|
|
d64146683e | ||
|
|
0e7914010f | ||
|
|
cfc7d8a2b5 | ||
|
|
f5cd659292 | ||
|
|
260138b427 | ||
|
|
2da149fd7e | ||
|
|
e33887718d | ||
|
|
ba4f4f4672 | ||
|
|
b7a57ce120 | ||
|
|
82abbc7234 | ||
|
|
ba98149022 | ||
|
|
7fd44a3e12 | ||
|
|
6e8d561090 | ||
|
|
cb762f4cad | ||
|
|
eed6866b7e | ||
|
|
25a6bfa9ee | ||
|
|
b3f8f2a5c1 | ||
|
|
cc8b5a543b | ||
|
|
10d5415bcb | ||
|
|
827cbe7f97 | ||
|
|
0d84517fbc | ||
|
|
7fa1da20fb | ||
|
|
f13a161ead | ||
|
|
c4cda301aa | ||
|
|
13fda30051 | ||
|
|
a3146ab1ca | ||
|
|
c0cf87356e | ||
|
|
6c3e4ef441 | ||
|
|
6c038830a8 | ||
|
|
064a293b80 | ||
|
|
79c47e29ee | ||
|
|
be87a29a9d | ||
|
|
280dffb5e1 | ||
|
|
336993ea06 | ||
|
|
516cb10000 | ||
|
|
1cdd5e3424 | ||
|
|
bd78c6ade2 | ||
|
|
5ce35faa86 | ||
|
|
484b572e6b | ||
|
|
81805a45f0 | ||
|
|
c457752f36 | ||
|
|
289289bfd3 | ||
|
|
09274307e8 | ||
|
|
d8718dcf54 | ||
|
|
fb9eeba422 | ||
|
|
2d2630ef07 | ||
|
|
1f22e035e3 | ||
|
|
a6a7584d79 | ||
|
|
ffac4f6ec3 | ||
|
|
032a84b167 | ||
|
|
3357aaef4b | ||
|
|
d9ed43d112 | ||
|
|
e160a52bfd | ||
|
|
9067ae47d1 | ||
|
|
71e807b3be | ||
|
|
1e2df07544 | ||
|
|
860841468c | ||
|
|
ed4ecc3255 | ||
|
|
b999e4b1e2 | ||
|
|
8ce227047d | ||
|
|
523515f936 | ||
|
|
10da3bc8dd | ||
|
|
eb0dd74040 | ||
|
|
61200d2171 | ||
|
|
e8aebee3f6 | ||
|
|
210083bdd8 | ||
|
|
c33c9dc585 | ||
|
|
056c212975 | ||
|
|
381203c084 | ||
|
|
76c47a9a43 | ||
|
|
9209e57c5a | ||
|
|
333f1bd9ce | ||
|
|
002caadf9e | ||
|
|
311ba29d0f | ||
|
|
237a64d922 | ||
|
|
d4af2dd5cf | ||
|
|
a36ce585ce | ||
|
|
29ec6df24f | ||
|
|
8b17508ef1 | ||
|
|
abaf0a198d | ||
|
|
454c6d9c2f | ||
|
|
cae5503e34 | ||
|
|
34e9786a41 | ||
|
|
5467d45dfa | ||
|
|
ac87137c1c | ||
|
|
e0bccfd2d9 | ||
|
|
7b6e55a2e0 | ||
|
|
5c374b5793 | ||
|
|
ffdd0de522 | ||
|
|
5370968839 |
@@ -33,4 +33,5 @@ rustflags = [
|
||||
"-Wclippy::rc_buffer",
|
||||
"-Wclippy::rc_mutex",
|
||||
"-Wclippy::rest_pat_in_fully_bound_structs",
|
||||
"-Wunreachable_pub"
|
||||
]
|
||||
|
||||
@@ -12,3 +12,6 @@ indent_size = 2
|
||||
|
||||
[*.{rs,py}]
|
||||
indent_size = 4
|
||||
|
||||
[*.snap]
|
||||
trim_trailing_whitespace = false
|
||||
53
.github/workflows/ci.yaml
vendored
53
.github/workflows/ci.yaml
vendored
@@ -15,6 +15,8 @@ env:
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
PACKAGE_NAME: ruff
|
||||
PYTHON_VERSION: "3.7" # to build abi3 wheels
|
||||
|
||||
jobs:
|
||||
cargo-fmt:
|
||||
@@ -121,15 +123,6 @@ jobs:
|
||||
- run: cargo check
|
||||
- run: cargo fmt --all --check
|
||||
|
||||
typos:
|
||||
name: "spell check"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
|
||||
ecosystem:
|
||||
name: "ecosystem"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -203,6 +196,28 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python-package:
|
||||
name: "python package"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
manylinux: auto
|
||||
args: --out dist
|
||||
- name: "Test wheel"
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
|
||||
pre-commit:
|
||||
name: "pre-commit"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -230,3 +245,23 @@ jobs:
|
||||
exit_code=${PIPESTATUS[0]}
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
exit $exit_code
|
||||
|
||||
docs:
|
||||
name: "mkdocs"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Install dependencies"
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: "Update README File"
|
||||
run: python scripts/transform_readme.py --target mkdocs
|
||||
- name: "Generate docs"
|
||||
run: python scripts/generate_mkdocs.py
|
||||
- name: "Check docs formatting"
|
||||
run: python scripts/check_docs_formatted.py
|
||||
- name: "Build docs"
|
||||
run: mkdocs build --strict
|
||||
|
||||
@@ -18,6 +18,31 @@ env:
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
sdist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build sdist"
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
command: sdist
|
||||
args: --out dist
|
||||
- name: "Test sdist"
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload sdist"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
|
||||
macos-x86_64:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
@@ -32,10 +57,12 @@ jobs:
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
target: x86_64
|
||||
args: --release --out dist --sdist
|
||||
- name: "Install built wheel - x86_64"
|
||||
args: --release --out dist
|
||||
- name: "Test wheel - x86_64"
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -43,9 +70,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-x86_64-apple-darwin.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-x86_64-apple-darwin.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -68,9 +95,11 @@ jobs:
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
args: --release --universal2 --out dist
|
||||
- name: "Install built wheel - universal2"
|
||||
- name: "Test wheel - universal2"
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -78,9 +107,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-aarch64-apple-darwin.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-aarch64-apple-darwin.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -113,11 +142,13 @@ jobs:
|
||||
with:
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: "Test wheel"
|
||||
if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -126,9 +157,9 @@ jobs:
|
||||
- name: "Archive binary"
|
||||
shell: bash
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.zip
|
||||
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
|
||||
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.zip
|
||||
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
|
||||
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -158,10 +189,12 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: "Test wheel"
|
||||
if: ${{ startsWith(matrix.target, 'x86_64') }}
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -169,9 +202,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -187,6 +220,9 @@ jobs:
|
||||
platform:
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
arch: aarch64
|
||||
# see https://github.com/charliermarsh/ruff/issues/3791
|
||||
# and https://github.com/gnzlbg/jemallocator/issues/170#issuecomment-1503228963
|
||||
maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
|
||||
- target: armv7-unknown-linux-gnueabihf
|
||||
arch: armv7
|
||||
- target: s390x-unknown-linux-gnu
|
||||
@@ -195,6 +231,7 @@ jobs:
|
||||
arch: ppc64le
|
||||
- target: powerpc64-unknown-linux-gnu
|
||||
arch: ppc64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
@@ -207,10 +244,11 @@ jobs:
|
||||
with:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: auto
|
||||
docker-options: ${{ matrix.platform.maturin_docker_options }}
|
||||
args: --release --out dist
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
if: matrix.platform.arch != 'ppc64'
|
||||
name: Install built wheel
|
||||
name: Test wheel
|
||||
with:
|
||||
arch: ${{ matrix.platform.arch }}
|
||||
distro: ubuntu20.04
|
||||
@@ -221,6 +259,7 @@ jobs:
|
||||
pip3 install -U pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -228,9 +267,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -260,7 +299,7 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: "Test wheel"
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
@@ -269,6 +308,8 @@ jobs:
|
||||
run: |
|
||||
apk add py3-pip
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -276,9 +317,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -294,8 +335,10 @@ jobs:
|
||||
platform:
|
||||
- target: aarch64-unknown-linux-musl
|
||||
arch: aarch64
|
||||
maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16
|
||||
- target: armv7-unknown-linux-musleabihf
|
||||
arch: armv7
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
@@ -309,8 +352,9 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
docker-options: ${{ matrix.platform.maturin_docker_options }}
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Install built wheel
|
||||
name: Test wheel
|
||||
with:
|
||||
arch: ${{ matrix.platform.arch }}
|
||||
distro: alpine_latest
|
||||
@@ -319,6 +363,7 @@ jobs:
|
||||
apk add py3-pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
ruff check --help
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -326,9 +371,9 @@ jobs:
|
||||
path: dist
|
||||
- name: "Archive binary"
|
||||
run: |
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||
- name: "Upload binary"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,8 @@
|
||||
crates/ruff/resources/test/cpython
|
||||
mkdocs.yml
|
||||
.overrides
|
||||
ruff-old
|
||||
github_search*.jsonl
|
||||
|
||||
###
|
||||
# Rust.gitignore
|
||||
|
||||
@@ -23,6 +23,11 @@ repos:
|
||||
- MD033 # no-inline-html
|
||||
- --
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.14.8
|
||||
hooks:
|
||||
- id: typos
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cargo-fmt
|
||||
@@ -58,11 +63,6 @@ repos:
|
||||
rev: 23.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
exclude: |
|
||||
(?x)^(
|
||||
crates/ruff/resources/.*|
|
||||
crates/ruff_python_formatter/resources/.*
|
||||
)$
|
||||
|
||||
ci:
|
||||
skip: [cargo-fmt, clippy, dev-generate-all]
|
||||
|
||||
@@ -1,5 +1,71 @@
|
||||
# Breaking Changes
|
||||
|
||||
## 0.0.268
|
||||
|
||||
### The `keep-runtime-typing` setting has been removed ([#4427](https://github.com/charliermarsh/ruff/pull/4427))
|
||||
|
||||
Enabling the `keep-runtime-typing` option, located under the `pyupgrade` section, is equivalent
|
||||
to ignoring the `UP006` and `UP007` rules via Ruff's standard `ignore` mechanism. As there's no
|
||||
need for a dedicated setting to disable these rules, the `keep-runtime-typing` option has been
|
||||
removed.
|
||||
|
||||
## 0.0.267
|
||||
|
||||
### `update-check` is no longer a valid configuration option ([#4313](https://github.com/charliermarsh/ruff/pull/4313))
|
||||
|
||||
The `update-check` functionality was deprecated in [#2530](https://github.com/charliermarsh/ruff/pull/2530),
|
||||
in that the behavior itself was removed, and Ruff was changed to warn when that option was enabled.
|
||||
|
||||
Now, Ruff will throw an error when `update-check` is provided via a configuration file (e.g.,
|
||||
`update-check = false`) or through the command-line, since it has no effect. Users should remove
|
||||
this option from their configuration.
|
||||
|
||||
## 0.0.265
|
||||
|
||||
### `--fix-only` now exits with a zero exit code, unless `--exit-non-zero-on-fix` is specified ([#4146](https://github.com/charliermarsh/ruff/pull/4146))
|
||||
|
||||
Previously, `--fix-only` would exit with a non-zero exit code if any fixes were applied. This
|
||||
behavior was inconsistent with `--fix`, and further, meant that `--exit-non-zero-on-fix` was
|
||||
effectively ignored when `--fix-only` was specified.
|
||||
|
||||
Now, `--fix-only` will exit with a zero exit code, unless `--exit-non-zero-on-fix` is specified,
|
||||
in which case it will exit with a non-zero exit code if any fixes were applied.
|
||||
|
||||
## 0.0.260
|
||||
|
||||
### Fixes are now represented as a list of edits ([#3709](https://github.com/charliermarsh/ruff/pull/3709))
|
||||
|
||||
Previously, Ruff represented each fix as a single edit, which prohibited Ruff from automatically
|
||||
fixing violations that required multiple edits across a file. As such, Ruff now represents each
|
||||
fix as a list of edits.
|
||||
|
||||
This primarily affects the JSON API. Ruff's JSON representation used to represent the `fix` field as
|
||||
a single edit, like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Remove unused import: `sys`",
|
||||
"content": "",
|
||||
"location": {"row": 1, "column": 0},
|
||||
"end_location": {"row": 2, "column": 0}
|
||||
}
|
||||
```
|
||||
|
||||
The updated representation instead includes a list of edits:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Remove unused import: `sys`",
|
||||
"edits": [
|
||||
{
|
||||
"content": "",
|
||||
"location": {"row": 1, "column": 0},
|
||||
"end_location": {"row": 2, "column": 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 0.0.246
|
||||
|
||||
### `multiple-statements-on-one-line-def` (`E704`) was removed ([#2773](https://github.com/charliermarsh/ruff/pull/2773))
|
||||
|
||||
@@ -106,7 +106,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
|
||||
1. In that file, define a violation struct. You can grep for `#[violation]` to see examples.
|
||||
1. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
|
||||
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
|
||||
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast/mod.rs` (for AST-based
|
||||
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
|
||||
(for text-based checks), or `crates/ruff/src/checkers/filesystem.rs` (for filesystem-based
|
||||
checks).
|
||||
@@ -116,8 +116,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
To define the violation, start by creating a dedicated file for your rule under the appropriate
|
||||
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
|
||||
contain a struct defined via `#[violation]`, along with a function that creates the violation
|
||||
based on any required inputs. (Many of the existing examples live in `crates/ruff/src/violations.rs`,
|
||||
but we're looking to place new rules in their own files.)
|
||||
based on any required inputs.
|
||||
|
||||
To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`,
|
||||
which defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
|
||||
@@ -215,6 +214,20 @@ them to [PyPI](https://pypi.org/project/ruff/).
|
||||
Ruff follows the [semver](https://semver.org/) versioning standard. However, as pre-1.0 software,
|
||||
even patch releases may contain [non-backwards-compatible changes](https://semver.org/#spec-item-4).
|
||||
|
||||
## Ecosystem CI
|
||||
|
||||
GitHub Actions will run your changes against a number of real-world projects from GitHub and
|
||||
report on any diagnostic differences. You can also run those checks locally via:
|
||||
|
||||
```shell
|
||||
python scripts/check_ecosystem.py path/to/your/ruff path/to/older/ruff
|
||||
```
|
||||
|
||||
You can also run the Ecosystem CI check in a Docker container across a larger set of projects by
|
||||
downloading the [`known-github-tomls.json`](https://github.com/akx/ruff-usage-aggregate/blob/master/data/known-github-tomls.jsonl)
|
||||
as `github_search.jsonl` and following the instructions in [scripts/Dockerfile.ecosystem](https://github.com/charliermarsh/ruff/blob/main/scripts/Dockerfile.ecosystem).
|
||||
Note that this check will take a while to run.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
First, clone [CPython](https://github.com/python/cpython). It's a large and diverse Python codebase,
|
||||
|
||||
1337
Cargo.lock
generated
1337
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
@@ -3,7 +3,7 @@ members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
rust-version = "1.67"
|
||||
rust-version = "1.69"
|
||||
homepage = "https://beta.ruff.rs/docs/"
|
||||
documentation = "https://beta.ruff.rs/docs/"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
@@ -11,7 +11,7 @@ authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = { version = "1.0.69" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
bitflags = { version = "2.3.1" }
|
||||
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
colored = { version = "2.0.0" }
|
||||
@@ -31,11 +31,10 @@ proc-macro2 = { version = "1.0.51" }
|
||||
quote = { version = "1.0.23" }
|
||||
regex = { version = "1.7.1" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
|
||||
rustpython-parser = { features = [
|
||||
"lalrpop",
|
||||
"serde",
|
||||
], git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
|
||||
ruff_text_size = { git = "https://github.com/RustPython/Parser.git", rev = "3654cf0bdfc270df6b2b83e2df086843574ad082" }
|
||||
rustpython-format = { git = "https://github.com/RustPython/Parser.git", rev = "3654cf0bdfc270df6b2b83e2df086843574ad082" }
|
||||
rustpython-literal = { git = "https://github.com/RustPython/Parser.git", rev = "3654cf0bdfc270df6b2b83e2df086843574ad082" }
|
||||
rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "3654cf0bdfc270df6b2b83e2df086843574ad082", default-features = false, features = ["full-lexer", "all-nodes-with-ranges"] }
|
||||
schemars = { version = "0.8.12" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
||||
@@ -44,7 +43,7 @@ similar = { version = "2.2.1" }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
syn = { version = "1.0.109" }
|
||||
syn = { version = "2.0.15" }
|
||||
test-case = { version = "3.0.0" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
toml = { version = "0.7.2" }
|
||||
|
||||
80
LICENSE
80
LICENSE
@@ -354,6 +354,37 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-todos, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2019 EclecticIQ. All rights reserved.
|
||||
Copyright (c) 2020 Gram <gram@orsinium.dev>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
- flake8-unused-arguments, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
@@ -550,6 +581,30 @@ are:
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
- flynt, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-2022 Ilya Kamenshchikov
|
||||
|
||||
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:
|
||||
"""
|
||||
@@ -759,6 +814,31 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-async, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Cooper Lees
|
||||
|
||||
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-type-checking, licensed as follows:
|
||||
"""
|
||||
Copyright (c) 2021, Sondre Lillebø Gundersen
|
||||
|
||||
151
README.md
151
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
# Ruff
|
||||
|
||||
[](https://github.com/charliermarsh/ruff)
|
||||
[](https://github.com/charliermarsh/ruff)
|
||||
[](https://pypi.python.org/pypi/ruff)
|
||||
[](https://pypi.python.org/pypi/ruff)
|
||||
[](https://pypi.python.org/pypi/ruff)
|
||||
@@ -47,16 +47,16 @@ all while executing tens or hundreds of times faster than any individual tool.
|
||||
|
||||
Ruff is extremely actively developed and used in major open-source projects like:
|
||||
|
||||
- [pandas](https://github.com/pandas-dev/pandas)
|
||||
- [FastAPI](https://github.com/tiangolo/fastapi)
|
||||
- [Transformers (Hugging Face)](https://github.com/huggingface/transformers)
|
||||
- [Apache Airflow](https://github.com/apache/airflow)
|
||||
- [FastAPI](https://github.com/tiangolo/fastapi)
|
||||
- [Hugging Face](https://github.com/huggingface/transformers)
|
||||
- [Pandas](https://github.com/pandas-dev/pandas)
|
||||
- [SciPy](https://github.com/scipy/scipy)
|
||||
|
||||
...and many more.
|
||||
|
||||
Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster) or
|
||||
the most recent [project update](https://notes.crmarsh.com/ruff-the-first-200-releases).
|
||||
Ruff is backed by [Astral](https://astral.sh). Read the [launch post](https://astral.sh/blog/announcing-astral-the-company-behind-ruff),
|
||||
or the original [project announcement](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
|
||||
|
||||
## Testimonials
|
||||
|
||||
@@ -137,7 +137,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.261'
|
||||
rev: 'v0.0.269'
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -183,6 +183,7 @@ exclude = [
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
@@ -248,6 +249,7 @@ quality tools, including:
|
||||
- [eradicate](https://pypi.org/project/eradicate/)
|
||||
- [flake8-2020](https://pypi.org/project/flake8-2020/)
|
||||
- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
|
||||
- [flake8-async](https://pypi.org/project/flake8-async)
|
||||
- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
|
||||
- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
|
||||
- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
|
||||
@@ -262,6 +264,7 @@ quality tools, including:
|
||||
- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
|
||||
- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
|
||||
- [flake8-executable](https://pypi.org/project/flake8-executable/)
|
||||
- [flake8-future-annotations](https://pypi.org/project/flake8-future-annotations/)
|
||||
- [flake8-gettext](https://pypi.org/project/flake8-gettext/)
|
||||
- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
@@ -278,14 +281,16 @@ quality tools, including:
|
||||
- [flake8-simplify](https://pypi.org/project/flake8-simplify/)
|
||||
- [flake8-super](https://pypi.org/project/flake8-super/)
|
||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||
- [flake8-todos](https://pypi.org/project/flake8-todos/)
|
||||
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
||||
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
|
||||
- [flynt](https://pypi.org/project/flynt/) ([#2102](https://github.com/charliermarsh/ruff/issues/2102))
|
||||
- [isort](https://pypi.org/project/isort/)
|
||||
- [mccabe](https://pypi.org/project/mccabe/)
|
||||
- [pandas-vet](https://pypi.org/project/pandas-vet/)
|
||||
- [pep8-naming](https://pypi.org/project/pep8-naming/)
|
||||
- [pydocstyle](https://pypi.org/project/pydocstyle/)
|
||||
- [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
|
||||
- [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks)
|
||||
- [pyupgrade](https://pypi.org/project/pyupgrade/)
|
||||
- [tryceratops](https://pypi.org/project/tryceratops/)
|
||||
- [yesqa](https://pypi.org/project/yesqa/)
|
||||
@@ -332,56 +337,98 @@ Ruff is released under the MIT license.
|
||||
|
||||
## Who's Using Ruff?
|
||||
|
||||
Ruff is used in a number of major open-source projects, including:
|
||||
Ruff is used by a number of major open-source projects and companies, including:
|
||||
|
||||
- [pandas](https://github.com/pandas-dev/pandas)
|
||||
- [FastAPI](https://github.com/tiangolo/fastapi)
|
||||
- [Transformers (Hugging Face)](https://github.com/huggingface/transformers)
|
||||
- [Diffusers (Hugging Face)](https://github.com/huggingface/diffusers)
|
||||
- Amazon ([AWS SAM](https://github.com/aws/serverless-application-model))
|
||||
- [Apache Airflow](https://github.com/apache/airflow)
|
||||
- [SciPy](https://github.com/scipy/scipy)
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [PostHog](https://github.com/PostHog/posthog)
|
||||
- [Dagster](https://github.com/dagster-io/dagster)
|
||||
- [Dagger](https://github.com/dagger/dagger)
|
||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||
- [Hatch](https://github.com/pypa/hatch)
|
||||
- [PDM](https://github.com/pdm-project/pdm)
|
||||
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
||||
- [Great Expectations](https://github.com/great-expectations/great_expectations)
|
||||
- [ONNX](https://github.com/onnx/onnx)
|
||||
- [Polars](https://github.com/pola-rs/polars)
|
||||
- [Ibis](https://github.com/ibis-project/ibis)
|
||||
- [Synapse (Matrix)](https://github.com/matrix-org/synapse)
|
||||
- [SnowCLI (Snowflake)](https://github.com/Snowflake-Labs/snowcli)
|
||||
- [Dispatch (Netflix)](https://github.com/Netflix/dispatch)
|
||||
- [Saleor](https://github.com/saleor/saleor)
|
||||
- [Pynecone](https://github.com/pynecone-io/pynecone)
|
||||
- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
|
||||
- [Home Assistant](https://github.com/home-assistant/core)
|
||||
- [Pylint](https://github.com/PyCQA/pylint)
|
||||
- [Cryptography (PyCA)](https://github.com/pyca/cryptography)
|
||||
- [cibuildwheel (PyPA)](https://github.com/pypa/cibuildwheel)
|
||||
- [build (PyPA)](https://github.com/pypa/build)
|
||||
- AstraZeneca ([Magnus](https://github.com/AstraZeneca/magnus-core))
|
||||
- Benchling ([Refac](https://github.com/benchling/refac))
|
||||
- [Babel](https://github.com/python-babel/babel)
|
||||
- [featuretools](https://github.com/alteryx/featuretools)
|
||||
- [meson-python](https://github.com/mesonbuild/meson-python)
|
||||
- [ZenML](https://github.com/zenml-io/zenml)
|
||||
- [delta-rs](https://github.com/delta-io/delta-rs)
|
||||
- [Starlite](https://github.com/starlite-api/starlite)
|
||||
- [telemetry-airflow (Mozilla)](https://github.com/mozilla/telemetry-airflow)
|
||||
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
|
||||
- [PaddlePaddle](https://github.com/PaddlePaddle/Paddle)
|
||||
- [nox](https://github.com/wntrblm/nox)
|
||||
- [Neon](https://github.com/neondatabase/neon)
|
||||
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
||||
- [Openverse](https://github.com/WordPress/openverse)
|
||||
- [MegaLinter](https://github.com/oxsecurity/megalinter)
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Cryptography (PyCA)](https://github.com/pyca/cryptography)
|
||||
- [DVC](https://github.com/iterative/dvc)
|
||||
- [Dagger](https://github.com/dagger/dagger)
|
||||
- [Dagster](https://github.com/dagster-io/dagster)
|
||||
- [FastAPI](https://github.com/tiangolo/fastapi)
|
||||
- [Gradio](https://github.com/gradio-app/gradio)
|
||||
- [Great Expectations](https://github.com/great-expectations/great_expectations)
|
||||
- Hugging Face ([Transformers](https://github.com/huggingface/transformers), [Datasets](https://github.com/huggingface/datasets), [Diffusers](https://github.com/huggingface/diffusers))
|
||||
- [Hatch](https://github.com/pypa/hatch)
|
||||
- [Home Assistant](https://github.com/home-assistant/core)
|
||||
- [Ibis](https://github.com/ibis-project/ibis)
|
||||
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
||||
- [LangChain](https://github.com/hwchase17/langchain)
|
||||
- [LlamaIndex](https://github.com/jerryjliu/llama_index)
|
||||
- Matrix ([Synapse](https://github.com/matrix-org/synapse))
|
||||
- Meltano ([Meltano CLI](https://github.com/meltano/meltano), [Singer SDK](https://github.com/meltano/sdk))
|
||||
- Modern Treasury ([Python SDK](https://github.com/Modern-Treasury/modern-treasury-python-sdk))
|
||||
- Mozilla ([Firefox](https://github.com/mozilla/gecko-dev))
|
||||
- [MegaLinter](https://github.com/oxsecurity/megalinter)
|
||||
- Microsoft ([Semantic Kernel](https://github.com/microsoft/semantic-kernel), [ONNX Runtime](https://github.com/microsoft/onnxruntime), [LightGBM](https://github.com/microsoft/LightGBM))
|
||||
- Netflix ([Dispatch](https://github.com/Netflix/dispatch))
|
||||
- [Neon](https://github.com/neondatabase/neon)
|
||||
- [ONNX](https://github.com/onnx/onnx)
|
||||
- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
|
||||
- [PDM](https://github.com/pdm-project/pdm)
|
||||
- [PaddlePaddle](https://github.com/PaddlePaddle/Paddle)
|
||||
- [Pandas](https://github.com/pandas-dev/pandas)
|
||||
- [Poetry](https://github.com/python-poetry/poetry)
|
||||
- [Polars](https://github.com/pola-rs/polars)
|
||||
- [PostHog](https://github.com/PostHog/posthog)
|
||||
- Prefect ([Python SDK](https://github.com/PrefectHQ/prefect), [Marvin](https://github.com/PrefectHQ/marvin))
|
||||
- [PyInstaller](https://github.com/pyinstaller/pyinstaller)
|
||||
- [PyTorch](https://github.com/pytorch/pytorch)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [Pylint](https://github.com/PyCQA/pylint)
|
||||
- [Pynecone](https://github.com/pynecone-io/pynecone)
|
||||
- [Robyn](https://github.com/sansyrox/robyn)
|
||||
- Scale AI ([Launch SDK](https://github.com/scaleapi/launch-python-client))
|
||||
- Snowflake ([SnowCLI](https://github.com/Snowflake-Labs/snowcli))
|
||||
- [Saleor](https://github.com/saleor/saleor)
|
||||
- [SciPy](https://github.com/scipy/scipy)
|
||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
|
||||
- [Starlite](https://github.com/starlite-api/starlite)
|
||||
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
||||
- [Vega-Altair](https://github.com/altair-viz/altair)
|
||||
- WordPress ([Openverse](https://github.com/WordPress/openverse))
|
||||
- [ZenML](https://github.com/zenml-io/zenml)
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [build (PyPA)](https://github.com/pypa/build)
|
||||
- [cibuildwheel (PyPA)](https://github.com/pypa/cibuildwheel)
|
||||
- [delta-rs](https://github.com/delta-io/delta-rs)
|
||||
- [featuretools](https://github.com/alteryx/featuretools)
|
||||
- [meson-python](https://github.com/mesonbuild/meson-python)
|
||||
- [nox](https://github.com/wntrblm/nox)
|
||||
|
||||
### Show Your Support
|
||||
|
||||
If you're using Ruff, consider adding the Ruff badge to project's `README.md`:
|
||||
|
||||
```md
|
||||
[](https://github.com/charliermarsh/ruff)
|
||||
```
|
||||
|
||||
...or `README.rst`:
|
||||
|
||||
```rst
|
||||
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
|
||||
:target: https://github.com/charliermarsh/ruff
|
||||
:alt: Ruff
|
||||
```
|
||||
|
||||
...or, as HTML:
|
||||
|
||||
```html
|
||||
<a href="https://github.com/charliermarsh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
<div align="center">
|
||||
<a target="_blank" href="https://astral.sh" style="background:none">
|
||||
<img src="https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/svg/Astral.svg">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -5,3 +5,6 @@ extend-exclude = ["snapshots", "black"]
|
||||
trivias = "trivias"
|
||||
hel = "hel"
|
||||
whos = "whos"
|
||||
spawnve = "spawnve"
|
||||
ned = "ned"
|
||||
poit = "poit"
|
||||
|
||||
8
assets/badge/v2.json
Normal file
8
assets/badge/v2.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "",
|
||||
"message": "Ruff",
|
||||
"logoSvg": "<svg width=\"510\" height=\"622\" viewBox=\"0 0 510 622\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M206.701 0C200.964 0 196.314 4.64131 196.314 10.3667V41.4667C196.314 47.192 191.663 51.8333 185.927 51.8333H156.843C151.107 51.8333 146.456 56.4746 146.456 62.2V145.133C146.456 150.859 141.806 155.5 136.069 155.5H106.986C101.249 155.5 96.5988 160.141 96.5988 165.867V222.883C96.5988 228.609 91.9484 233.25 86.2118 233.25H57.1283C51.3917 233.25 46.7413 237.891 46.7413 243.617V300.633C46.7413 306.359 42.0909 311 36.3544 311H10.387C4.6504 311 0 315.641 0 321.367V352.467C0 358.192 4.6504 362.833 10.387 362.833H145.418C151.154 362.833 155.804 367.475 155.804 373.2V430.217C155.804 435.942 151.154 440.583 145.418 440.583H116.334C110.597 440.583 105.947 445.225 105.947 450.95V507.967C105.947 513.692 101.297 518.333 95.5601 518.333H66.4766C60.74 518.333 56.0896 522.975 56.0896 528.7V611.633C56.0896 617.359 60.74 622 66.4766 622H149.572C155.309 622 159.959 617.359 159.959 611.633V570.167H201.507C207.244 570.167 211.894 565.525 211.894 559.8V528.7C211.894 522.975 216.544 518.333 222.281 518.333H251.365C257.101 518.333 261.752 513.692 261.752 507.967V476.867C261.752 471.141 266.402 466.5 272.138 466.5H301.222C306.959 466.5 311.609 461.859 311.609 456.133V425.033C311.609 419.308 316.259 414.667 321.996 414.667H351.079C356.816 414.667 361.466 410.025 361.466 404.3V373.2C361.466 367.475 366.117 362.833 371.853 362.833H400.937C406.673 362.833 411.324 358.192 411.324 352.467V321.367C411.324 315.641 415.974 311 421.711 311H450.794C456.531 311 461.181 306.359 461.181 300.633V217.7C461.181 211.975 456.531 207.333 450.794 207.333H420.672C414.936 207.333 410.285 202.692 410.285 196.967V165.867C410.285 160.141 414.936 155.5 420.672 155.5H449.756C455.492 155.5 460.143 150.859 460.143 145.133V114.033C460.143 108.308 464.793 103.667 470.53 103.667H499.613C505.35 103.667 510 99.0253 510 93.3V10.3667C510 4.64132 505.35 0 499.613 0H206.701ZM168.269 440.583C162.532 440.583 157.882 445.225 157.882 450.95V507.967C157.882 513.692 153.231 518.333 147.495 518.333H118.411C112.675 518.333 108.024 522.975 108.024 528.7V559.8C108.024 565.525 112.675 570.167 118.411 570.167H159.959V528.7C159.959 522.975 164.61 518.333 170.346 518.333H199.43C205.166 518.333 209.817 513.692 209.817 507.967V476.867C209.817 471.141 214.467 466.5 220.204 466.5H249.287C255.024 466.5 259.674 461.859 259.674 456.133V425.033C259.674 419.308 264.325 414.667 270.061 414.667H299.145C304.881 414.667 309.532 410.025 309.532 404.3V373.2C309.532 367.475 314.182 362.833 319.919 362.833H349.002C354.739 362.833 359.389 358.192 359.389 352.467V321.367C359.389 315.641 364.039 311 369.776 311H398.859C404.596 311 409.246 306.359 409.246 300.633V269.533C409.246 263.808 404.596 259.167 398.859 259.167H318.88C313.143 259.167 308.493 254.525 308.493 248.8V217.7C308.493 211.975 313.143 207.333 318.88 207.333H347.963C353.7 207.333 358.35 202.692 358.35 196.967V165.867C358.35 160.141 363.001 155.5 368.737 155.5H397.821C403.557 155.5 408.208 150.859 408.208 145.133V114.033C408.208 108.308 412.858 103.667 418.595 103.667H447.678C453.415 103.667 458.065 99.0253 458.065 93.3V62.2C458.065 56.4746 453.415 51.8333 447.678 51.8333H208.778C203.041 51.8333 198.391 56.4746 198.391 62.2V145.133C198.391 150.859 193.741 155.5 188.004 155.5H158.921C153.184 155.5 148.534 160.141 148.534 165.867V222.883C148.534 228.609 143.883 233.25 138.147 233.25H109.063C103.327 233.25 98.6762 237.891 98.6762 243.617V300.633C98.6762 306.359 103.327 311 109.063 311H197.352C203.089 311 207.739 315.641 207.739 321.367V430.217C207.739 435.942 203.089 440.583 197.352 440.583H168.269Z\" fill=\"#D7FF64\"/></svg>",
|
||||
"logoWidth": 10,
|
||||
"labelColor": "grey",
|
||||
"color": "#261230"
|
||||
}
|
||||
24
assets/svg/Astral.svg
Normal file
24
assets/svg/Astral.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg width="139" height="24" viewBox="0 0 139 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="138.764" height="24" rx="2.18182" fill="#261230"/>
|
||||
<path
|
||||
d="M8.72798 15.2726H9.91316V11.8697L9.6887 10.4062L9.8952 10.3343L12.1309 15.1649L14.3486 10.3343L14.5461 10.4062L14.3486 11.8607V15.2726H15.5248V8.72714H13.9535L12.2117 12.7137H12.0142L10.2723 8.72714H8.72798V15.2726Z"
|
||||
fill="#D7FF64"/>
|
||||
<path
|
||||
d="M22.3432 15.2726H23.6631L21.3017 8.72714H19.7574L17.4589 15.2726H18.7069L19.1558 13.9797H21.9033L22.3432 15.2726ZM19.497 13.0279L19.901 11.8607L20.4308 10.0021H20.6463L21.176 11.8607L21.5711 13.0279H19.497Z"
|
||||
fill="#D7FF64"/>
|
||||
<path
|
||||
d="M25.4209 15.2726H28.1234C30.1077 15.2726 30.9876 14.1413 30.9876 12.0044C30.9876 9.92131 30.1706 8.72714 28.1234 8.72714H25.4209V15.2726ZM26.624 14.2131V9.77765H28.0965C29.147 9.77765 29.7306 10.1907 29.7306 11.4477V12.5521C29.7306 13.6923 29.2817 14.2131 28.0965 14.2131H26.624Z"
|
||||
fill="#D7FF64"/>
|
||||
<path
|
||||
d="M33.079 15.2726H37.6491V14.2131H34.2822V12.3815H37.2002V11.3938H34.2822V9.77765H37.6491V8.72714H33.079V15.2726Z"
|
||||
fill="#D7FF64"/>
|
||||
<path
|
||||
d="M42.923 15.2726H46.2451C47.4572 15.2726 48.2025 14.5812 48.2025 13.5487C48.2025 12.7675 47.8343 12.175 47.0532 11.9954V11.7799C47.6637 11.5734 48.0319 11.0436 48.0319 10.3433C48.0319 9.38259 47.4572 8.72714 46.281 8.72714H42.923V15.2726ZM44.0992 11.4746V9.65195H45.9578C46.4875 9.65195 46.7928 9.92131 46.7928 10.3523V10.7653C46.7928 11.1873 46.4965 11.4746 45.9758 11.4746H44.0992ZM44.0992 14.3388V12.3904H46.0296C46.5863 12.3904 46.9365 12.6418 46.9365 13.1806V13.5666C46.9365 14.0425 46.5684 14.3388 45.9309 14.3388H44.0992Z"
|
||||
fill="#D7FF64"/>
|
||||
<path
|
||||
d="M49.6959 8.72714L52.174 12.579V14.1952H50.1898V15.2726H53.3772V12.579L55.8553 8.72714H54.4456L53.5119 10.2535L52.8744 11.3759H52.6679L52.0483 10.2715L51.1056 8.72714H49.6959Z"
|
||||
fill="#D7FF64"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M74.1824 7.63626C74.1824 7.03377 74.6708 6.54535 75.2733 6.54535H84.0006C84.6031 6.54535 85.0915 7.03377 85.0915 7.63626V9.81808H80.0733V8.94535H79.2006V10.6908H84.0006C84.6031 10.6908 85.0915 11.1792 85.0915 11.7817V16.3635C85.0915 16.966 84.6031 17.4544 84.0006 17.4544H75.2733C74.6708 17.4544 74.1824 16.966 74.1824 16.3635V14.1817L79.2006 14.1817V15.0544H80.0733V13.309L75.2733 13.309C74.6708 13.309 74.1824 12.8206 74.1824 12.2181V7.63626ZM63.4912 6.54545C62.8887 6.54545 62.4003 7.03387 62.4003 7.63636V17.4545H67.4185V14.1818H68.2912V17.4545H73.3094V7.63636C73.3094 7.03387 72.821 6.54545 72.2185 6.54545H63.4912ZM69.164 10.6909V11.5636H66.5458V10.6909H69.164ZM110.619 6.54545C110.016 6.54545 109.528 7.03387 109.528 7.63636V17.4545H114.546V14.1818H115.419V17.4545H120.437V7.63636C120.437 7.03387 119.948 6.54545 119.346 6.54545H110.619ZM116.291 10.6909V11.5636H113.673V10.6909H116.291ZM91.8549 8.29091H96.8731V11.3455C96.8731 11.9479 96.3847 12.4364 95.7822 12.4364H91.8549V13.3091H96.8731V17.4545H87.9276C87.3251 17.4545 86.8367 16.9661 86.8367 16.3636V12.4364H85.964V8.29091H86.8367V6.54545H91.8549V8.29091ZM108.655 7.63636C108.655 7.03387 108.166 6.54545 107.564 6.54545H97.7458V17.4545H102.764V14.1818H103.637V17.4545H108.655V13.3091H106.473V12.4364H107.564C108.166 12.4364 108.655 11.9479 108.655 11.3455V7.63636ZM104.509 10.6909V11.5636H101.891V10.6909H104.509ZM132.218 13.3091L126.327 13.3091V6.54547L121.309 6.54547V17.4546H132.218V13.3091Z"
|
||||
fill="#D7FF64"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.269"
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ requires-python = ">=3.7"
|
||||
repository = "https://github.com/charliermarsh/ruff#subdirectory=crates/flake8_to_ruff"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
requires = ["maturin>=0.15.2,<0.16"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[tool.maturin]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.269"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
@@ -17,17 +17,19 @@ name = "ruff"
|
||||
ruff_cache = { path = "../ruff_cache" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast", features = ["serde"] }
|
||||
ruff_python_semantic = { path = "../ruff_python_semantic" }
|
||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||
ruff_text_size = { workspace = true }
|
||||
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
anyhow = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive", "string"], optional = true }
|
||||
colored = { workspace = true }
|
||||
dirs = { version = "4.0.0" }
|
||||
dirs = { version = "5.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
@@ -48,15 +50,17 @@ path-absolutize = { workspace = true, features = [
|
||||
] }
|
||||
pathdiff = { version = "0.2.1" }
|
||||
pep440_rs = { version = "0.3.1", features = ["serde"] }
|
||||
quick-junit = { version = "0.3.2" }
|
||||
regex = { workspace = true }
|
||||
result-like = { version = "0.4.6" }
|
||||
rustc-hash = { workspace = true }
|
||||
rustpython-common = { workspace = true }
|
||||
rustpython-format = { workspace = true }
|
||||
rustpython-parser = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
similar = { workspace = true, features = ["inline"] }
|
||||
shellexpand = { workspace = true }
|
||||
smallvec = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
@@ -68,11 +72,14 @@ typed-arena = { version = "2.0.2" }
|
||||
unicode-width = { version = "0.1.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { workspace = true, features = ["yaml", "redactions"] }
|
||||
insta = { workspace = true }
|
||||
pretty_assertions = "1.3.0"
|
||||
test-case = { workspace = true }
|
||||
# Disable colored output in tests
|
||||
colored = { workspace = true, features = ["no-color"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
logical_lines = []
|
||||
schemars = ["dep:schemars"]
|
||||
jupyter_notebook = []
|
||||
ecosystem_ci = []
|
||||
|
||||
@@ -9,7 +9,13 @@ def foo(x, y, z):
|
||||
print(x, y, z)
|
||||
|
||||
# This is a real comment.
|
||||
# # This is a (nested) comment.
|
||||
#return True
|
||||
return False
|
||||
|
||||
#import os # noqa: ERA001
|
||||
|
||||
|
||||
class A():
|
||||
pass
|
||||
# b = c
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import Any, Type
|
||||
from typing_extensions import override
|
||||
|
||||
# Error
|
||||
def foo(a, b):
|
||||
@@ -94,6 +95,31 @@ class Foo:
|
||||
def foo(self: "Foo", a: int, *params: str, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
@override
|
||||
def foo(self: "Foo", a: Any, *params: str, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
@override
|
||||
def foo(self: "Foo", a: int, *params: str, **options: str) -> Any:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
@override
|
||||
def foo(self: "Foo", a: int, *params: Any, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
@override
|
||||
def foo(self: "Foo", a: int, *params: Any, **options: str) -> int:
|
||||
pass
|
||||
|
||||
# ANN401
|
||||
@override
|
||||
def foo(self: "Foo", a: int, *params: str, **options: Any) -> int:
|
||||
pass
|
||||
|
||||
# OK
|
||||
@classmethod
|
||||
def foo(cls: Type["Foo"], a: int, b: int) -> int:
|
||||
|
||||
23
crates/ruff/resources/test/fixtures/flake8_async/ASYNC100.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/flake8_async/ASYNC100.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import urllib.request
|
||||
import requests
|
||||
import httpx
|
||||
|
||||
|
||||
async def foo():
|
||||
urllib.request.urlopen("http://example.com/foo/bar").read()
|
||||
|
||||
|
||||
async def foo():
|
||||
requests.get()
|
||||
|
||||
|
||||
async def foo():
|
||||
httpx.get()
|
||||
|
||||
|
||||
async def foo():
|
||||
requests.post()
|
||||
|
||||
|
||||
async def foo():
|
||||
httpx.post()
|
||||
31
crates/ruff/resources/test/fixtures/flake8_async/ASYNC101.py
vendored
Normal file
31
crates/ruff/resources/test/fixtures/flake8_async/ASYNC101.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
|
||||
async def foo():
|
||||
open("foo")
|
||||
|
||||
|
||||
async def foo():
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
async def foo():
|
||||
subprocess.run("foo")
|
||||
|
||||
|
||||
async def foo():
|
||||
subprocess.call("foo")
|
||||
|
||||
|
||||
async def foo():
|
||||
subprocess.foo(0)
|
||||
|
||||
|
||||
async def foo():
|
||||
os.wait4(10)
|
||||
|
||||
|
||||
async def foo():
|
||||
os.wait(12)
|
||||
13
crates/ruff/resources/test/fixtures/flake8_async/ASYNC102.py
vendored
Normal file
13
crates/ruff/resources/test/fixtures/flake8_async/ASYNC102.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import os
|
||||
|
||||
|
||||
async def foo():
|
||||
os.popen()
|
||||
|
||||
|
||||
async def foo():
|
||||
os.spawnl()
|
||||
|
||||
|
||||
async def foo():
|
||||
os.fspath("foo")
|
||||
@@ -1,11 +1,13 @@
|
||||
# Error
|
||||
assert True
|
||||
assert True # S101
|
||||
|
||||
|
||||
def fn():
|
||||
x = 1
|
||||
assert x == 1 # S101
|
||||
assert x == 2 # S101
|
||||
|
||||
# Error
|
||||
assert x == 1
|
||||
|
||||
# Error
|
||||
assert x == 2
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
assert True # OK
|
||||
|
||||
20
crates/ruff/resources/test/fixtures/flake8_bandit/S602.py
vendored
Normal file
20
crates/ruff/resources/test/fixtures/flake8_bandit/S602.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
from subprocess import Popen, call, check_call, check_output, run
|
||||
|
||||
# Check different Popen wrappers are checked.
|
||||
Popen("true", shell=True)
|
||||
call("true", shell=True)
|
||||
check_call("true", shell=True)
|
||||
check_output("true", shell=True)
|
||||
run("true", shell=True)
|
||||
|
||||
# Check values that truthy values are treated as true.
|
||||
Popen("true", shell=1)
|
||||
Popen("true", shell=[1])
|
||||
Popen("true", shell={1: 1})
|
||||
Popen("true", shell=(1,))
|
||||
|
||||
# Check command argument looks unsafe.
|
||||
var_string = "true"
|
||||
Popen(var_string, shell=True)
|
||||
Popen([var_string], shell=True)
|
||||
Popen([var_string, ""], shell=True)
|
||||
20
crates/ruff/resources/test/fixtures/flake8_bandit/S603.py
vendored
Normal file
20
crates/ruff/resources/test/fixtures/flake8_bandit/S603.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
from subprocess import Popen, call, check_call, check_output, run
|
||||
|
||||
# Different Popen wrappers are checked.
|
||||
Popen("true", shell=False)
|
||||
call("true", shell=False)
|
||||
check_call("true", shell=False)
|
||||
check_output("true", shell=False)
|
||||
run("true", shell=False)
|
||||
|
||||
# Values that falsey values are treated as false.
|
||||
Popen("true", shell=0)
|
||||
Popen("true", shell=[])
|
||||
Popen("true", shell={})
|
||||
Popen("true", shell=None)
|
||||
|
||||
# Unknown values are treated as falsey.
|
||||
Popen("true", shell=True if True else False)
|
||||
|
||||
# No value is also caught.
|
||||
Popen("true")
|
||||
5
crates/ruff/resources/test/fixtures/flake8_bandit/S604.py
vendored
Normal file
5
crates/ruff/resources/test/fixtures/flake8_bandit/S604.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
def foo(shell):
|
||||
pass
|
||||
|
||||
|
||||
foo(shell=True)
|
||||
25
crates/ruff/resources/test/fixtures/flake8_bandit/S605.py
vendored
Normal file
25
crates/ruff/resources/test/fixtures/flake8_bandit/S605.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
|
||||
import commands
|
||||
import popen2
|
||||
|
||||
# Check all shell functions.
|
||||
os.system("true")
|
||||
os.popen("true")
|
||||
os.popen2("true")
|
||||
os.popen3("true")
|
||||
os.popen4("true")
|
||||
popen2.popen2("true")
|
||||
popen2.popen3("true")
|
||||
popen2.popen4("true")
|
||||
popen2.Popen3("true")
|
||||
popen2.Popen4("true")
|
||||
commands.getoutput("true")
|
||||
commands.getstatusoutput("true")
|
||||
|
||||
|
||||
# Check command argument looks unsafe.
|
||||
var_string = "true"
|
||||
os.system(var_string)
|
||||
os.system([var_string])
|
||||
os.system([var_string, ""])
|
||||
20
crates/ruff/resources/test/fixtures/flake8_bandit/S606.py
vendored
Normal file
20
crates/ruff/resources/test/fixtures/flake8_bandit/S606.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import os
|
||||
|
||||
# Check all shell functions.
|
||||
os.execl("true")
|
||||
os.execle("true")
|
||||
os.execlp("true")
|
||||
os.execlpe("true")
|
||||
os.execv("true")
|
||||
os.execve("true")
|
||||
os.execvp("true")
|
||||
os.execvpe("true")
|
||||
os.spawnl("true")
|
||||
os.spawnle("true")
|
||||
os.spawnlp("true")
|
||||
os.spawnlpe("true")
|
||||
os.spawnv("true")
|
||||
os.spawnve("true")
|
||||
os.spawnvp("true")
|
||||
os.spawnvpe("true")
|
||||
os.startfile("true")
|
||||
44
crates/ruff/resources/test/fixtures/flake8_bandit/S607.py
vendored
Normal file
44
crates/ruff/resources/test/fixtures/flake8_bandit/S607.py
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
|
||||
# Check all functions.
|
||||
subprocess.Popen("true")
|
||||
subprocess.call("true")
|
||||
subprocess.check_call("true")
|
||||
subprocess.check_output("true")
|
||||
subprocess.run("true")
|
||||
os.system("true")
|
||||
os.popen("true")
|
||||
os.popen2("true")
|
||||
os.popen3("true")
|
||||
os.popen4("true")
|
||||
popen2.popen2("true")
|
||||
popen2.popen3("true")
|
||||
popen2.popen4("true")
|
||||
popen2.Popen3("true")
|
||||
popen2.Popen4("true")
|
||||
commands.getoutput("true")
|
||||
commands.getstatusoutput("true")
|
||||
os.execl("true")
|
||||
os.execle("true")
|
||||
os.execlp("true")
|
||||
os.execlpe("true")
|
||||
os.execv("true")
|
||||
os.execve("true")
|
||||
os.execvp("true")
|
||||
os.execvpe("true")
|
||||
os.spawnl("true")
|
||||
os.spawnle("true")
|
||||
os.spawnlp("true")
|
||||
os.spawnlpe("true")
|
||||
os.spawnv("true")
|
||||
os.spawnve("true")
|
||||
os.spawnvp("true")
|
||||
os.spawnvpe("true")
|
||||
os.startfile("true")
|
||||
|
||||
# Check it does not fail for full paths.
|
||||
os.system("/bin/ls")
|
||||
os.system("./bin/ls")
|
||||
os.system(["/bin/ls"])
|
||||
os.system(["/bin/ls", "/tmp"])
|
||||
os.system(r"C:\\bin\ls")
|
||||
@@ -74,8 +74,8 @@ def query40():
|
||||
|
||||
def query41():
|
||||
return (
|
||||
"SELECT *"
|
||||
"FROM table"
|
||||
"SELECT * "
|
||||
"FROM table "
|
||||
f"WHERE var = {var}"
|
||||
)
|
||||
|
||||
@@ -84,7 +84,7 @@ query42 = cursor.execute("SELECT * FROM table WHERE var = %s" % var)
|
||||
query43 = cursor.execute(f"SELECT * FROM table WHERE var = {var}")
|
||||
query44 = cursor.execute("SELECT * FROM table WHERE var = {}".format(var))
|
||||
query45 = cursor.executemany("SELECT * FROM table WHERE var = %s" % var, [])
|
||||
|
||||
|
||||
# # pass
|
||||
query = "SELECT * FROM table WHERE id = 1"
|
||||
query = "DELETE FROM table WHERE id = 1"
|
||||
@@ -93,3 +93,12 @@ query = "UPDATE table SET id = 1"
|
||||
cursor.execute('SELECT * FROM table WHERE id = %s', var)
|
||||
cursor.execute('SELECT * FROM table WHERE id = 1')
|
||||
cursor.executemany('SELECT * FROM table WHERE id = %s', [var, var2])
|
||||
|
||||
# # INSERT without INTO (e.g. MySQL and derivatives)
|
||||
query = "INSERT table VALUES (%s)" % (var,)
|
||||
|
||||
# # REPLACE (e.g. MySQL and derivatives, SQLite)
|
||||
query = "REPLACE INTO table VALUES (%s)" % (var,)
|
||||
query = "REPLACE table VALUES (%s)" % (var,)
|
||||
|
||||
query = "Deselect something that is not SQL even though it has a ' from ' somewhere in %s." % "there"
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""
|
||||
Should emit:
|
||||
B017 - on lines 20
|
||||
B017 - on lines 23 and 41
|
||||
"""
|
||||
import asyncio
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
CONSTANT = True
|
||||
|
||||
@@ -34,3 +35,14 @@ class Foobar(unittest.TestCase):
|
||||
def raises_with_absolute_reference(self):
|
||||
with self.assertRaises(asyncio.CancelledError):
|
||||
Foo()
|
||||
|
||||
|
||||
def test_pytest_raises():
|
||||
with pytest.raises(Exception):
|
||||
raise ValueError("Hello")
|
||||
|
||||
with pytest.raises(Exception, "hello"):
|
||||
raise ValueError("This is fine")
|
||||
|
||||
with pytest.raises(Exception, match="hello"):
|
||||
raise ValueError("This is also fine")
|
||||
|
||||
@@ -172,3 +172,14 @@ def iter_f(names):
|
||||
|
||||
if False:
|
||||
return [lambda: i for i in range(3)] # error
|
||||
|
||||
|
||||
for val in range(3):
|
||||
def make_func(val=val):
|
||||
def tmp():
|
||||
return print(val)
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
funcs.append(make_func())
|
||||
|
||||
@@ -4,7 +4,12 @@ B027 - on lines 13, 16, 19, 23
|
||||
"""
|
||||
import abc
|
||||
from abc import ABC
|
||||
from abc import abstractmethod, abstractproperty
|
||||
from abc import (
|
||||
abstractmethod,
|
||||
abstractproperty,
|
||||
abstractclassmethod,
|
||||
abstractstaticmethod,
|
||||
)
|
||||
from abc import abstractmethod as notabstract
|
||||
from abc import abstractproperty as notabstract_property
|
||||
|
||||
@@ -55,6 +60,22 @@ class AbstractClass(ABC):
|
||||
def abstract_6(self):
|
||||
...
|
||||
|
||||
@abstractclassmethod
|
||||
def abstract_7(self):
|
||||
pass
|
||||
|
||||
@abc.abstractclassmethod
|
||||
def abstract_8(self):
|
||||
...
|
||||
|
||||
@abstractstaticmethod
|
||||
def abstract_9(self):
|
||||
pass
|
||||
|
||||
@abc.abstractstaticmethod
|
||||
def abstract_10(self):
|
||||
...
|
||||
|
||||
def body_1(self):
|
||||
print("foo")
|
||||
...
|
||||
|
||||
@@ -78,6 +78,21 @@ for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
for shopper in shoppers:
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
_ = [collect_shop_items(shopper, section_items) for shopper in shoppers] # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
# The variable is overridden, skip checking.
|
||||
_ = [_ for section_items in range(3)]
|
||||
_ = [collect_shop_items(shopper, section_items) for shopper in shoppers]
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
_ = [item for item in section_items]
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
# The iterator is being used for the second time.
|
||||
_ = [(item1, item2) for item1 in section_items for item2 in section_items] # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
if _section == "greens":
|
||||
collect_shop_items(shopper, section_items)
|
||||
@@ -134,6 +149,16 @@ for group in groupby(items, key=lambda p: p[1]):
|
||||
collect_shop_items("Joe", group[1])
|
||||
|
||||
|
||||
# https://github.com/charliermarsh/ruff/issues/4050
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
if _section == "greens":
|
||||
for item in section_items:
|
||||
collect_shop_items(shopper, item)
|
||||
elif _section == "frozen items":
|
||||
_ = [item for item in section_items]
|
||||
else:
|
||||
collect_shop_items(shopper, section_items)
|
||||
|
||||
# Make sure we ignore - but don't fail on more complicated invocations
|
||||
for _key, (_value1, _value2) in groupby(
|
||||
[("a", (1, 2)), ("b", (3, 4)), ("a", (5, 6))], key=lambda p: p[1]
|
||||
|
||||
@@ -631,3 +631,11 @@ result = function(
|
||||
the_first_one = next(
|
||||
(i for i in range(10) if i // 2 == 0) # COM812 fix should include the final bracket
|
||||
)
|
||||
|
||||
foo = namedtuple(
|
||||
name="foo",
|
||||
status="bar",
|
||||
message="sfdsdfsdgs fsdfsdf output!dsfdfsdjkg ghfskdjghkdssd sd fsdf s\n"[
|
||||
:20
|
||||
],
|
||||
)
|
||||
|
||||
@@ -7,11 +7,14 @@ set(set(x))
|
||||
set(list(x))
|
||||
set(tuple(x))
|
||||
set(sorted(x))
|
||||
set(sorted(x, key=lambda y: y))
|
||||
set(reversed(x))
|
||||
sorted(list(x))
|
||||
sorted(tuple(x))
|
||||
sorted(sorted(x))
|
||||
sorted(sorted(x, key=lambda y: y))
|
||||
sorted(reversed(x))
|
||||
sorted(list(x), key=lambda y: y)
|
||||
tuple(
|
||||
list(
|
||||
[x, 3, "hell"\
|
||||
|
||||
10
crates/ruff/resources/test/fixtures/flake8_comprehensions/C418.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/flake8_comprehensions/C418.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
dict({})
|
||||
dict({'a': 1})
|
||||
dict({'x': 1 for x in range(10)})
|
||||
dict(
|
||||
{'x': 1 for x in range(10)}
|
||||
)
|
||||
|
||||
dict({}, a=1)
|
||||
dict({x: 1 for x in range(1)}, a=1)
|
||||
|
||||
39
crates/ruff/resources/test/fixtures/flake8_comprehensions/C419.py
vendored
Normal file
39
crates/ruff/resources/test/fixtures/flake8_comprehensions/C419.py
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
any([x.id for x in bar])
|
||||
all([x.id for x in bar])
|
||||
any( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
all( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
any({x.id for x in bar})
|
||||
|
||||
# OK
|
||||
all(x.id for x in bar)
|
||||
all(x.id for x in bar)
|
||||
any(x.id for x in bar)
|
||||
all((x.id for x in bar))
|
||||
|
||||
|
||||
async def f() -> bool:
|
||||
return all([await use_greeting(greeting) for greeting in await greetings()])
|
||||
|
||||
|
||||
# Special comment handling
|
||||
any(
|
||||
[ # lbracket comment
|
||||
# second line comment
|
||||
i.bit_count()
|
||||
# random middle comment
|
||||
for i in range(5) # rbracket comment
|
||||
] # rpar comment
|
||||
# trailing comment
|
||||
)
|
||||
|
||||
# Weird case where the function call, opening bracket, and comment are all
|
||||
# on the same line.
|
||||
any([ # lbracket comment
|
||||
# second line comment
|
||||
i.bit_count() for i in range(5) # rbracket comment
|
||||
] # rpar comment
|
||||
)
|
||||
@@ -21,3 +21,36 @@ def f_c():
|
||||
def f_ok():
|
||||
msg = "hello"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
def f_unfixable():
|
||||
msg = "hello"
|
||||
raise RuntimeError("This is an example exception")
|
||||
|
||||
|
||||
def f_msg_in_nested_scope():
|
||||
def nested():
|
||||
msg = "hello"
|
||||
|
||||
raise RuntimeError("This is an example exception")
|
||||
|
||||
|
||||
def f_msg_in_parent_scope():
|
||||
msg = "hello"
|
||||
|
||||
def nested():
|
||||
raise RuntimeError("This is an example exception")
|
||||
|
||||
|
||||
def f_fix_indentation_check(foo):
|
||||
if foo:
|
||||
raise RuntimeError("This is an example exception")
|
||||
else:
|
||||
if foo == "foo":
|
||||
raise RuntimeError(f"This is an exception: {foo}")
|
||||
raise RuntimeError("This is an exception: {}".format(foo))
|
||||
|
||||
|
||||
# Report these, but don't fix them
|
||||
if foo: raise RuntimeError("This is an example exception")
|
||||
if foo: x = 1; raise RuntimeError("This is an example exception")
|
||||
|
||||
7
crates/ruff/resources/test/fixtures/flake8_future_annotations/edge_case.py
vendored
Normal file
7
crates/ruff/resources/test/fixtures/flake8_future_annotations/edge_case.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
from typing import List
|
||||
import typing as t
|
||||
|
||||
|
||||
def main(_: List[int]) -> None:
|
||||
a_list: t.List[str] = []
|
||||
a_list.append("hello")
|
||||
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/from_typing_import.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/from_typing_import.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
from typing import List
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list: List[str] = []
|
||||
a_list.append("hello")
|
||||
8
crates/ruff/resources/test/fixtures/flake8_future_annotations/from_typing_import_many.py
vendored
Normal file
8
crates/ruff/resources/test/fixtures/flake8_future_annotations/from_typing_import_many.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
from typing import Dict, List, Optional, Set, Union, cast
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list: List[Optional[str]] = []
|
||||
a_list.append("hello")
|
||||
a_dict = cast(Dict[int | None, Union[int, Set[bool]]], {})
|
||||
a_dict[1] = {True, False}
|
||||
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/import_typing.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/import_typing.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import typing
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list: typing.List[str] = []
|
||||
a_list.append("hello")
|
||||
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/import_typing_as.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/import_typing_as.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import typing as t
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list: t.List[str] = []
|
||||
a_list.append("hello")
|
||||
@@ -0,0 +1,7 @@
|
||||
def main() -> None:
|
||||
a_list: list[str] = []
|
||||
a_list.append("hello")
|
||||
|
||||
|
||||
def hello(y: dict[str, int]) -> None:
|
||||
del y
|
||||
7
crates/ruff/resources/test/fixtures/flake8_future_annotations/no_future_import_uses_union.py
vendored
Normal file
7
crates/ruff/resources/test/fixtures/flake8_future_annotations/no_future_import_uses_union.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
def main() -> None:
|
||||
a_list: list[str] | None = []
|
||||
a_list.append("hello")
|
||||
|
||||
|
||||
def hello(y: dict[str, int] | None) -> None:
|
||||
del y
|
||||
@@ -0,0 +1,8 @@
|
||||
def main() -> None:
|
||||
a_list: list[str | None] = []
|
||||
a_list.append("hello")
|
||||
|
||||
|
||||
def hello(y: dict[str | None, int]) -> None:
|
||||
z: tuple[str, str | None, str] = tuple(y)
|
||||
del z
|
||||
3
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_no_types.py
vendored
Normal file
3
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_no_types.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
def main() -> str:
|
||||
a_str = "hello"
|
||||
return a_str
|
||||
10
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_non_simplifiable_types.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_non_simplifiable_types.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
class Stuff(NamedTuple):
|
||||
x: int
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list = Stuff(5)
|
||||
print(a_list)
|
||||
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_uses_future.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_uses_future.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def main() -> None:
|
||||
a_list: list[str] = []
|
||||
a_list.append("hello")
|
||||
8
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_variable_name.py
vendored
Normal file
8
crates/ruff/resources/test/fixtures/flake8_future_annotations/ok_variable_name.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import typing
|
||||
|
||||
IRRELEVANT = typing.TypeVar
|
||||
|
||||
|
||||
def main() -> None:
|
||||
List: list[str] = []
|
||||
List.append("hello")
|
||||
16
crates/ruff/resources/test/fixtures/flake8_import_conventions/custom_banned.py
vendored
Normal file
16
crates/ruff/resources/test/fixtures/flake8_import_conventions/custom_banned.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import typing as t # banned
|
||||
import typing as ty # banned
|
||||
|
||||
import numpy as nmp # banned
|
||||
import numpy as npy # banned
|
||||
import tensorflow.keras.backend as K # banned
|
||||
import torch.nn.functional as F # banned
|
||||
from tensorflow.keras import backend as K # banned
|
||||
from torch.nn import functional as F # banned
|
||||
|
||||
from typing import Any # ok
|
||||
|
||||
import numpy as np # ok
|
||||
import tensorflow as tf # ok
|
||||
import torch.nn as nn # ok
|
||||
from tensorflow.keras import backend # ok
|
||||
10
crates/ruff/resources/test/fixtures/flake8_import_conventions/custom_banned_from.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/flake8_import_conventions/custom_banned_from.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
from logging.config import BaseConfigurator # banned
|
||||
from typing import Any, Dict # banned
|
||||
from typing import * # banned
|
||||
|
||||
from pandas import DataFrame # banned
|
||||
from pandas import * # banned
|
||||
|
||||
import logging.config # ok
|
||||
import typing # ok
|
||||
import pandas # ok
|
||||
@@ -7,3 +7,12 @@ foo.info("Hello {}".format("World!"))
|
||||
logging.log(logging.INFO, msg="Hello {}".format("World!"))
|
||||
logging.log(level=logging.INFO, msg="Hello {}".format("World!"))
|
||||
logging.log(msg="Hello {}".format("World!"), level=logging.INFO)
|
||||
|
||||
# Flask support
|
||||
import flask
|
||||
from flask import current_app
|
||||
from flask import current_app as app
|
||||
|
||||
flask.current_app.logger.info("Hello {}".format("World!"))
|
||||
current_app.logger.info("Hello {}".format("World!"))
|
||||
app.logger.log(logging.INFO, "Hello {}".format("World!"))
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# PIE802
|
||||
any([x.id for x in bar])
|
||||
all([x.id for x in bar])
|
||||
any( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
all( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
any({x.id for x in bar})
|
||||
|
||||
# OK
|
||||
all(x.id for x in bar)
|
||||
all(x.id for x in bar)
|
||||
any(x.id for x in bar)
|
||||
all((x.id for x in bar))
|
||||
|
||||
async def f() -> bool:
|
||||
return all([await use_greeting(greeting) for greeting in await greetings()])
|
||||
@@ -11,3 +11,7 @@ _T = TypeVar("_T") # OK
|
||||
_TTuple = TypeVarTuple("_TTuple") # OK
|
||||
|
||||
_P = ParamSpec("_P") # OK
|
||||
|
||||
|
||||
def f():
|
||||
T = TypeVar("T") # OK
|
||||
|
||||
@@ -11,3 +11,6 @@ _T = TypeVar("_T") # OK
|
||||
_TTuple = TypeVarTuple("_TTuple") # OK
|
||||
|
||||
_P = ParamSpec("_P") # OK
|
||||
|
||||
def f():
|
||||
T = TypeVar("T") # OK
|
||||
|
||||
@@ -46,3 +46,48 @@ field229: dict[int, int] = {1: 2, **{3: 4}} # Y015 Only simple default values a
|
||||
field23 = "foo" + "bar" # Y015 Only simple default values are allowed for assignments
|
||||
field24 = b"foo" + b"bar" # Y015 Only simple default values are allowed for assignments
|
||||
field25 = 5 * 5 # Y015 Only simple default values are allowed for assignments
|
||||
|
||||
# We shouldn't emit Y015 within functions
|
||||
def f():
|
||||
field26: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
|
||||
|
||||
# We shouldn't emit Y015 for __slots__ or __match_args__
|
||||
class Class1:
|
||||
__slots__ = (
|
||||
'_one',
|
||||
'_two',
|
||||
'_three',
|
||||
'_four',
|
||||
'_five',
|
||||
'_six',
|
||||
'_seven',
|
||||
'_eight',
|
||||
'_nine',
|
||||
'_ten',
|
||||
'_eleven',
|
||||
)
|
||||
|
||||
__match_args__ = (
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four',
|
||||
'five',
|
||||
'six',
|
||||
'seven',
|
||||
'eight',
|
||||
'nine',
|
||||
'ten',
|
||||
'eleven',
|
||||
)
|
||||
|
||||
# We shouldn't emit Y015 for __all__
|
||||
__all__ = ["Class1"]
|
||||
|
||||
# Ignore the following for PYI015
|
||||
field26 = typing.Sequence[int]
|
||||
field27 = list[str]
|
||||
field28 = builtins.str
|
||||
field29 = str
|
||||
field30 = str | bytes | None
|
||||
|
||||
@@ -53,3 +53,48 @@ field229: dict[int, int] = {1: 2, **{3: 4}} # Y015 Only simple default values a
|
||||
field23 = "foo" + "bar" # Y015 Only simple default values are allowed for assignments
|
||||
field24 = b"foo" + b"bar" # Y015 Only simple default values are allowed for assignments
|
||||
field25 = 5 * 5 # Y015 Only simple default values are allowed for assignments
|
||||
|
||||
# We shouldn't emit Y015 within functions
|
||||
def f():
|
||||
field26: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
|
||||
|
||||
# We shouldn't emit Y015 for __slots__ or __match_args__
|
||||
class Class1:
|
||||
__slots__ = (
|
||||
'_one',
|
||||
'_two',
|
||||
'_three',
|
||||
'_four',
|
||||
'_five',
|
||||
'_six',
|
||||
'_seven',
|
||||
'_eight',
|
||||
'_nine',
|
||||
'_ten',
|
||||
'_eleven',
|
||||
)
|
||||
|
||||
__match_args__ = (
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four',
|
||||
'five',
|
||||
'six',
|
||||
'seven',
|
||||
'eight',
|
||||
'nine',
|
||||
'ten',
|
||||
'eleven',
|
||||
)
|
||||
|
||||
# We shouldn't emit Y015 for __all__
|
||||
__all__ = ["Class1"]
|
||||
|
||||
# Ignore the following for PYI015
|
||||
field26 = typing.Sequence[int]
|
||||
field27 = list[str]
|
||||
field28 = builtins.str
|
||||
field29 = str
|
||||
field30 = str | bytes | None
|
||||
|
||||
35
crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py
vendored
Normal file
35
crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.py
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# Shouldn't affect non-union field types.
|
||||
field1: str
|
||||
|
||||
# Should emit for duplicate field types.
|
||||
field2: str | str # PYI016: Duplicate union member `str`
|
||||
|
||||
|
||||
# Should emit for union types in arguments.
|
||||
def func1(arg1: int | int): # PYI016: Duplicate union member `int`
|
||||
print(arg1)
|
||||
|
||||
|
||||
# Should emit for unions in return types.
|
||||
def func2() -> str | str: # PYI016: Duplicate union member `str`
|
||||
return "my string"
|
||||
|
||||
|
||||
# Should emit in longer unions, even if not directly adjacent.
|
||||
field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
|
||||
# Shouldn't emit for non-type unions.
|
||||
field7 = str | str
|
||||
|
||||
# Should emit for strangely-bracketed unions.
|
||||
field8: int | (str | int) # PYI016: Duplicate union member `int`
|
||||
|
||||
# Should handle user brackets when fixing.
|
||||
field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
|
||||
# Should emit for nested unions.
|
||||
field11: dict[int | int, str]
|
||||
32
crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi
vendored
Normal file
32
crates/ruff/resources/test/fixtures/flake8_pyi/PYI016.pyi
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# Shouldn't affect non-union field types.
|
||||
field1: str
|
||||
|
||||
# Should emit for duplicate field types.
|
||||
field2: str | str # PYI016: Duplicate union member `str`
|
||||
|
||||
# Should emit for union types in arguments.
|
||||
def func1(arg1: int | int): # PYI016: Duplicate union member `int`
|
||||
print(arg1)
|
||||
|
||||
# Should emit for unions in return types.
|
||||
def func2() -> str | str: # PYI016: Duplicate union member `str`
|
||||
return "my string"
|
||||
|
||||
# Should emit in longer unions, even if not directly adjacent.
|
||||
field3: str | str | int # PYI016: Duplicate union member `str`
|
||||
field4: int | int | str # PYI016: Duplicate union member `int`
|
||||
field5: str | int | str # PYI016: Duplicate union member `str`
|
||||
field6: int | bool | str | int # PYI016: Duplicate union member `int`
|
||||
|
||||
# Shouldn't emit for non-type unions.
|
||||
field7 = str | str
|
||||
|
||||
# Should emit for strangely-bracketed unions.
|
||||
field8: int | (str | int) # PYI016: Duplicate union member `int`
|
||||
|
||||
# Should handle user brackets when fixing.
|
||||
field9: int | (int | str) # PYI016: Duplicate union member `int`
|
||||
field10: (str | int) | str # PYI016: Duplicate union member `str`
|
||||
|
||||
# Should emit for nested unions.
|
||||
field11: dict[int | int, str]
|
||||
28
crates/ruff/resources/test/fixtures/flake8_pyi/PYI020.py
vendored
Normal file
28
crates/ruff/resources/test/fixtures/flake8_pyi/PYI020.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import sys
|
||||
import typing
|
||||
from typing import Annotated, Literal, TypeAlias, TypeVar
|
||||
|
||||
import typing_extensions
|
||||
|
||||
def f(x: "int"): ... # Y020 Quoted annotations should never be used in stubs
|
||||
def g(x: list["int"]): ... # Y020 Quoted annotations should never be used in stubs
|
||||
_T = TypeVar("_T", bound="int") # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
def h(w: Literal["a", "b"], x: typing.Literal["c"], y: typing_extensions.Literal["d"], z: _T) -> _T: ...
|
||||
|
||||
def j() -> "int": ... # Y020 Quoted annotations should never be used in stubs
|
||||
Alias: TypeAlias = list["int"] # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
class Child(list["int"]): # Y020 Quoted annotations should never be used in stubs
|
||||
"""Documented and guaranteed useful.""" # Y021 Docstrings should not be included in stubs
|
||||
|
||||
if sys.platform == "linux":
|
||||
f: "int" # Y020 Quoted annotations should never be used in stubs
|
||||
elif sys.platform == "win32":
|
||||
f: "str" # Y020 Quoted annotations should never be used in stubs
|
||||
else:
|
||||
f: "bytes" # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
# These two shouldn't trigger Y020 -- empty strings can't be "quoted annotations"
|
||||
k = "" # Y052 Need type annotation for "k"
|
||||
el = r"" # Y052 Need type annotation for "el"
|
||||
28
crates/ruff/resources/test/fixtures/flake8_pyi/PYI020.pyi
vendored
Normal file
28
crates/ruff/resources/test/fixtures/flake8_pyi/PYI020.pyi
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import sys
|
||||
import typing
|
||||
from typing import Annotated, Literal, TypeAlias, TypeVar
|
||||
|
||||
import typing_extensions
|
||||
|
||||
def f(x: "int"): ... # Y020 Quoted annotations should never be used in stubs
|
||||
def g(x: list["int"]): ... # Y020 Quoted annotations should never be used in stubs
|
||||
_T = TypeVar("_T", bound="int") # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
def h(w: Literal["a", "b"], x: typing.Literal["c"], y: typing_extensions.Literal["d"], z: _T) -> _T: ...
|
||||
|
||||
def j() -> "int": ... # Y020 Quoted annotations should never be used in stubs
|
||||
Alias: TypeAlias = list["int"] # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
class Child(list["int"]): # Y020 Quoted annotations should never be used in stubs
|
||||
"""Documented and guaranteed useful.""" # Y021 Docstrings should not be included in stubs
|
||||
|
||||
if sys.platform == "linux":
|
||||
f: "int" # Y020 Quoted annotations should never be used in stubs
|
||||
elif sys.platform == "win32":
|
||||
f: "str" # Y020 Quoted annotations should never be used in stubs
|
||||
else:
|
||||
f: "bytes" # Y020 Quoted annotations should never be used in stubs
|
||||
|
||||
# These two shouldn't trigger Y020 -- empty strings can't be "quoted annotations"
|
||||
k = "" # Y052 Need type annotation for "k"
|
||||
el = r"" # Y052 Need type annotation for "el"
|
||||
24
crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import typing
|
||||
from collections.abc import Mapping
|
||||
from typing import (
|
||||
Annotated,
|
||||
TypeAlias,
|
||||
Union,
|
||||
Literal,
|
||||
)
|
||||
|
||||
just_literals_pipe_union: TypeAlias = (
|
||||
Literal[True] | Literal["idk"]
|
||||
) # not PYI042 (not a stubfile)
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
_ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any
|
||||
_PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"]
|
||||
_PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
|
||||
snake_case_alias1: TypeAlias = str | int # not PYI042 (not a stubfile)
|
||||
_snake_case_alias2: TypeAlias = Literal["whatever"] # not PYI042 (not a stubfile)
|
||||
Snake_case_alias: TypeAlias = int | float # not PYI042 (not a stubfile)
|
||||
|
||||
# check that this edge case doesn't crash
|
||||
_: TypeAlias = str | int
|
||||
24
crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.pyi
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_pyi/PYI042.pyi
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import typing
|
||||
from collections.abc import Mapping
|
||||
from typing import (
|
||||
Annotated,
|
||||
TypeAlias,
|
||||
Union,
|
||||
Literal,
|
||||
)
|
||||
|
||||
just_literals_pipe_union: TypeAlias = (
|
||||
Literal[True] | Literal["idk"]
|
||||
) # PYI042, since not camel case
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
_ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any
|
||||
_PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"]
|
||||
_PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
|
||||
snake_case_alias1: TypeAlias = str | int # PYI042, since not camel case
|
||||
_snake_case_alias2: TypeAlias = Literal["whatever"] # PYI042, since not camel case
|
||||
Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
||||
|
||||
# check that this edge case doesn't crash
|
||||
_: TypeAlias = str | int
|
||||
23
crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import typing
|
||||
from collections.abc import Mapping
|
||||
from typing import (
|
||||
Annotated,
|
||||
TypeAlias,
|
||||
Union,
|
||||
Literal,
|
||||
)
|
||||
|
||||
_PrivateAliasT: TypeAlias = str | int # not PYI043 (not a stubfile)
|
||||
_PrivateAliasT2: TypeAlias = typing.Any # not PYI043 (not a stubfile)
|
||||
_PrivateAliasT3: TypeAlias = Literal[
|
||||
"not", "a", "chance"
|
||||
] # not PYI043 (not a stubfile)
|
||||
just_literals_pipe_union: TypeAlias = Literal[True] | Literal["idk"]
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
_ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any
|
||||
_PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"]
|
||||
_PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
|
||||
# check that this edge case doesn't crash
|
||||
_: TypeAlias = str | int
|
||||
23
crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.pyi
vendored
Normal file
23
crates/ruff/resources/test/fixtures/flake8_pyi/PYI043.pyi
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import typing
|
||||
from collections.abc import Mapping
|
||||
from typing import (
|
||||
Annotated,
|
||||
TypeAlias,
|
||||
Union,
|
||||
Literal,
|
||||
)
|
||||
|
||||
_PrivateAliasT: TypeAlias = str | int # PYI043, since this ends in a T
|
||||
_PrivateAliasT2: TypeAlias = typing.Any # PYI043, since this ends in a T
|
||||
_PrivateAliasT3: TypeAlias = Literal[
|
||||
"not", "a", "chance"
|
||||
] # PYI043, since this ends in a T
|
||||
just_literals_pipe_union: TypeAlias = Literal[True] | Literal["idk"]
|
||||
PublicAliasT: TypeAlias = str | int
|
||||
PublicAliasT2: TypeAlias = Union[str, bytes]
|
||||
_ABCDEFGHIJKLMNOPQRST: TypeAlias = typing.Any
|
||||
_PrivateAliasS: TypeAlias = Literal["I", "guess", "this", "is", "okay"]
|
||||
_PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
||||
|
||||
# check that this edge case doesn't crash
|
||||
_: TypeAlias = str | int
|
||||
93
crates/ruff/resources/test/fixtures/flake8_pyi/PYI052.py
vendored
Normal file
93
crates/ruff/resources/test/fixtures/flake8_pyi/PYI052.py
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import builtins
|
||||
import typing
|
||||
from typing import TypeAlias, Final
|
||||
|
||||
field1: int
|
||||
field2: int = ...
|
||||
field3 = ... # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
field4: int = 0
|
||||
field41: int = 0xFFFFFFFF
|
||||
field42: int = 1234567890
|
||||
field43: int = -0xFFFFFFFF
|
||||
field44: int = -1234567890
|
||||
field5 = 0 # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int") # Y052 Need type annotation for "field5"
|
||||
field6 = 0 # Y052 Need type annotation for "field6"
|
||||
field7 = b"" # Y052 Need type annotation for "field7"
|
||||
field71 = "foo" # Y052 Need type annotation for "field71"
|
||||
field72: str = "foo"
|
||||
field8 = False # Y052 Need type annotation for "field8"
|
||||
field81 = -1 # Y052 Need type annotation for "field81"
|
||||
field82: float = -98.43
|
||||
field83 = -42j # Y052 Need type annotation for "field83"
|
||||
field84 = 5 + 42j # Y052 Need type annotation for "field84"
|
||||
field85 = -5 - 42j # Y052 Need type annotation for "field85"
|
||||
field9 = None # Y026 Use typing_extensions.TypeAlias for type aliases, e.g. "field9: TypeAlias = None"
|
||||
Field95: TypeAlias = None
|
||||
Field96: TypeAlias = int | None
|
||||
Field97: TypeAlias = None | typing.SupportsInt | builtins.str | float | bool
|
||||
field19 = [1, 2, 3] # Y052 Need type annotation for "field19"
|
||||
field191: list[int] = [1, 2, 3]
|
||||
field20 = (1, 2, 3) # Y052 Need type annotation for "field20"
|
||||
field201: tuple[int, ...] = (1, 2, 3)
|
||||
field21 = {1, 2, 3} # Y052 Need type annotation for "field21"
|
||||
field211: set[int] = {1, 2, 3}
|
||||
field212 = {"foo": "bar"} # Y052 Need type annotation for "field212"
|
||||
field213: dict[str, str] = {"foo": "bar"}
|
||||
field22: Final = {"foo": 5}
|
||||
field221: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] # Y015 Only simple default values are allowed for assignments
|
||||
field223: list[int] = [*range(10)] # Y015 Only simple default values are allowed for assignments
|
||||
field224: list[int] = list(range(10)) # Y015 Only simple default values are allowed for assignments
|
||||
field225: list[object] = [{}, 1, 2] # Y015 Only simple default values are allowed for assignments
|
||||
field226: tuple[str | tuple[str, ...], ...] = ("foo", ("foo", "bar")) # Y015 Only simple default values are allowed for assignments
|
||||
field227: dict[str, object] = {"foo": {"foo": "bar"}} # Y015 Only simple default values are allowed for assignments
|
||||
field228: dict[str, list[object]] = {"foo": []} # Y015 Only simple default values are allowed for assignments
|
||||
# When parsed, this case results in `None` being placed in the `.keys` list for the `ast.Dict` node
|
||||
field229: dict[int, int] = {1: 2, **{3: 4}} # Y015 Only simple default values are allowed for assignments
|
||||
field23 = "foo" + "bar" # Y015 Only simple default values are allowed for assignments
|
||||
field24 = b"foo" + b"bar" # Y015 Only simple default values are allowed for assignments
|
||||
field25 = 5 * 5 # Y015 Only simple default values are allowed for assignments
|
||||
|
||||
# We shouldn't emit Y015 within functions
|
||||
def f():
|
||||
field26: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
|
||||
|
||||
# We shouldn't emit Y015 for __slots__ or __match_args__
|
||||
class Class1:
|
||||
__slots__ = (
|
||||
'_one',
|
||||
'_two',
|
||||
'_three',
|
||||
'_four',
|
||||
'_five',
|
||||
'_six',
|
||||
'_seven',
|
||||
'_eight',
|
||||
'_nine',
|
||||
'_ten',
|
||||
'_eleven',
|
||||
)
|
||||
|
||||
__match_args__ = (
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four',
|
||||
'five',
|
||||
'six',
|
||||
'seven',
|
||||
'eight',
|
||||
'nine',
|
||||
'ten',
|
||||
'eleven',
|
||||
)
|
||||
|
||||
# We shouldn't emit Y015 for __all__
|
||||
__all__ = ["Class1"]
|
||||
|
||||
# Ignore the following for PYI015
|
||||
field26 = typing.Sequence[int]
|
||||
field27 = list[str]
|
||||
field28 = builtins.str
|
||||
field29 = str
|
||||
field30 = str | bytes | None
|
||||
100
crates/ruff/resources/test/fixtures/flake8_pyi/PYI052.pyi
vendored
Normal file
100
crates/ruff/resources/test/fixtures/flake8_pyi/PYI052.pyi
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import builtins
|
||||
import typing
|
||||
from typing import TypeAlias, Final, NewType, TypeVar, TypeVarTuple, ParamSpec
|
||||
|
||||
# We shouldn't emit Y015 for simple default values
|
||||
field1: int
|
||||
field2: int = ...
|
||||
field3 = ... # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
field4: int = 0
|
||||
field41: int = 0xFFFFFFFF
|
||||
field42: int = 1234567890
|
||||
field43: int = -0xFFFFFFFF
|
||||
field44: int = -1234567890
|
||||
field5 = 0 # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int") # Y052 Need type annotation for "field5"
|
||||
field6 = 0 # Y052 Need type annotation for "field6"
|
||||
field7 = b"" # Y052 Need type annotation for "field7"
|
||||
field71 = "foo" # Y052 Need type annotation for "field71"
|
||||
field72: str = "foo"
|
||||
field8 = False # Y052 Need type annotation for "field8"
|
||||
field81 = -1 # Y052 Need type annotation for "field81"
|
||||
field82: float = -98.43
|
||||
field83 = -42j # Y052 Need type annotation for "field83"
|
||||
field84 = 5 + 42j # Y052 Need type annotation for "field84"
|
||||
field85 = -5 - 42j # Y052 Need type annotation for "field85"
|
||||
field9 = None # Y026 Use typing_extensions.TypeAlias for type aliases, e.g. "field9: TypeAlias = None"
|
||||
Field95: TypeAlias = None
|
||||
Field96: TypeAlias = int | None
|
||||
Field97: TypeAlias = None | typing.SupportsInt | builtins.str | float | bool
|
||||
Field98 = NewType('MyInt', int)
|
||||
Field99 = TypeVar('Field99')
|
||||
Field100 = TypeVarTuple('Field100')
|
||||
Field101 = ParamSpec('Field101')
|
||||
field19 = [1, 2, 3] # Y052 Need type annotation for "field19"
|
||||
field191: list[int] = [1, 2, 3]
|
||||
field20 = (1, 2, 3) # Y052 Need type annotation for "field20"
|
||||
field201: tuple[int, ...] = (1, 2, 3)
|
||||
field21 = {1, 2, 3} # Y052 Need type annotation for "field21"
|
||||
field211: set[int] = {1, 2, 3}
|
||||
field212 = {"foo": "bar"} # Y052 Need type annotation for "field212"
|
||||
field213: dict[str, str] = {"foo": "bar"}
|
||||
field22: Final = {"foo": 5}
|
||||
|
||||
# We *should* emit Y015 for more complex default values
|
||||
field221: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] # Y015 Only simple default values are allowed for assignments
|
||||
field223: list[int] = [*range(10)] # Y015 Only simple default values are allowed for assignments
|
||||
field224: list[int] = list(range(10)) # Y015 Only simple default values are allowed for assignments
|
||||
field225: list[object] = [{}, 1, 2] # Y015 Only simple default values are allowed for assignments
|
||||
field226: tuple[str | tuple[str, ...], ...] = ("foo", ("foo", "bar")) # Y015 Only simple default values are allowed for assignments
|
||||
field227: dict[str, object] = {"foo": {"foo": "bar"}} # Y015 Only simple default values are allowed for assignments
|
||||
field228: dict[str, list[object]] = {"foo": []} # Y015 Only simple default values are allowed for assignments
|
||||
# When parsed, this case results in `None` being placed in the `.keys` list for the `ast.Dict` node
|
||||
field229: dict[int, int] = {1: 2, **{3: 4}} # Y015 Only simple default values are allowed for assignments
|
||||
field23 = "foo" + "bar" # Y015 Only simple default values are allowed for assignments
|
||||
field24 = b"foo" + b"bar" # Y015 Only simple default values are allowed for assignments
|
||||
field25 = 5 * 5 # Y015 Only simple default values are allowed for assignments
|
||||
|
||||
# We shouldn't emit Y015 within functions
|
||||
def f():
|
||||
field26: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
|
||||
|
||||
# We shouldn't emit Y015 for __slots__ or __match_args__
|
||||
class Class1:
|
||||
__slots__ = (
|
||||
'_one',
|
||||
'_two',
|
||||
'_three',
|
||||
'_four',
|
||||
'_five',
|
||||
'_six',
|
||||
'_seven',
|
||||
'_eight',
|
||||
'_nine',
|
||||
'_ten',
|
||||
'_eleven',
|
||||
)
|
||||
|
||||
__match_args__ = (
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four',
|
||||
'five',
|
||||
'six',
|
||||
'seven',
|
||||
'eight',
|
||||
'nine',
|
||||
'ten',
|
||||
'eleven',
|
||||
)
|
||||
|
||||
# We shouldn't emit Y015 for __all__
|
||||
__all__ = ["Class1"]
|
||||
|
||||
# Ignore the following for PYI015
|
||||
field26 = typing.Sequence[int]
|
||||
field27 = list[str]
|
||||
field28 = builtins.str
|
||||
field29 = str
|
||||
field30 = str | bytes | None
|
||||
@@ -49,3 +49,18 @@ def test_list_expressions(param1, param2):
|
||||
@pytest.mark.parametrize([some_expr, "param2"], [1, 2, 3])
|
||||
def test_list_mixed_expr_literal(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("param1, " "param2, " "param3"), [(1, 2, 3), (4, 5, 6)])
|
||||
def test_implicit_str_concat_with_parens(param1, param2, param3):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param1, " "param2, " "param3", [(1, 2, 3), (4, 5, 6)])
|
||||
def test_implicit_str_concat_no_parens(param1, param2, param3):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize((("param1, " "param2, " "param3")), [(1, 2, 3), (4, 5, 6)])
|
||||
def test_implicit_str_concat_with_multi_parens(param1, param2, param3):
|
||||
...
|
||||
|
||||
@@ -39,3 +39,8 @@ def test_error():
|
||||
message
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
assert something # OK
|
||||
assert something and something_else # Error
|
||||
assert something and something_else and something_third # Error
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
###
|
||||
def x():
|
||||
a = 1
|
||||
return a # error
|
||||
return a # RET504
|
||||
|
||||
|
||||
# Can be refactored false positives
|
||||
@@ -211,10 +211,10 @@ def nonlocal_assignment():
|
||||
def decorator() -> Flask:
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/hello')
|
||||
@app.route("/hello")
|
||||
def hello() -> str:
|
||||
"""Hello endpoint."""
|
||||
return 'Hello, World!'
|
||||
return "Hello, World!"
|
||||
|
||||
return app
|
||||
|
||||
@@ -222,12 +222,13 @@ def decorator() -> Flask:
|
||||
def default():
|
||||
y = 1
|
||||
|
||||
def f(x = y) -> X:
|
||||
def f(x=y) -> X:
|
||||
return x
|
||||
|
||||
return y
|
||||
|
||||
|
||||
# Multiple assignment
|
||||
def get_queryset(option_1, option_2):
|
||||
queryset: Any = None
|
||||
queryset = queryset.filter(a=1)
|
||||
@@ -246,4 +247,28 @@ def get_queryset():
|
||||
|
||||
def get_queryset():
|
||||
queryset = Model.filter(a=1)
|
||||
return queryset # error
|
||||
return queryset # RET504
|
||||
|
||||
|
||||
# Function arguments
|
||||
def str_to_bool(val):
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
val = val.strip().lower()
|
||||
if val in ("1", "true", "yes"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def str_to_bool(val):
|
||||
if isinstance(val, bool):
|
||||
return val
|
||||
val = 1
|
||||
return val # RET504
|
||||
|
||||
|
||||
def str_to_bool(val):
|
||||
if isinstance(val, bool):
|
||||
return some_obj
|
||||
return val
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
def foo():
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except ValueError: # SIM105
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except (ValueError, OSError): # SIM105
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except: # SIM105
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except (a.Error, b.Error): # SIM105
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
print('foo')
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
print('bar')
|
||||
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
finally:
|
||||
print('bar')
|
||||
|
||||
try:
|
||||
foo()
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
for i in range(3):
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def bar():
|
||||
try:
|
||||
return foo()
|
||||
except ValueError:
|
||||
pass
|
||||
96
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_0.py
vendored
Normal file
96
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_0.py
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
def foo():
|
||||
pass
|
||||
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except (ValueError, OSError):
|
||||
pass
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except:
|
||||
pass
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except (a.Error, b.Error):
|
||||
pass
|
||||
|
||||
# OK
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
print("foo")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# OK
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
print("bar")
|
||||
|
||||
# OK
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
finally:
|
||||
print("bar")
|
||||
|
||||
# OK
|
||||
try:
|
||||
foo()
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# OK
|
||||
try:
|
||||
for i in range(3):
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def bar():
|
||||
# OK
|
||||
try:
|
||||
return foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def with_ellipsis():
|
||||
# OK
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
...
|
||||
|
||||
|
||||
def with_ellipsis_and_return():
|
||||
# OK
|
||||
try:
|
||||
return foo()
|
||||
except ValueError:
|
||||
...
|
||||
|
||||
|
||||
def with_comment():
|
||||
try:
|
||||
foo()
|
||||
except (ValueError, OSError):
|
||||
pass # Trailing comment.
|
||||
8
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_1.py
vendored
Normal file
8
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_1.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Case: There's a random import, so it should add `contextlib` after it."""
|
||||
import math
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
math.sqrt(-1)
|
||||
except ValueError:
|
||||
pass
|
||||
13
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_2.py
vendored
Normal file
13
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_2.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
"""Case: `contextlib` already imported."""
|
||||
import contextlib
|
||||
|
||||
|
||||
def foo():
|
||||
pass
|
||||
|
||||
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
16
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_3.py
vendored
Normal file
16
crates/ruff/resources/test/fixtures/flake8_simplify/SIM105_3.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"""Case: `contextlib` is imported after the call site."""
|
||||
|
||||
|
||||
def foo():
|
||||
pass
|
||||
|
||||
|
||||
def bar():
|
||||
# SIM105
|
||||
try:
|
||||
foo()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
import contextlib
|
||||
@@ -12,3 +12,10 @@ if not a == b: # OK
|
||||
|
||||
if not a != b: # OK
|
||||
pass
|
||||
|
||||
a = not not b # SIM208
|
||||
|
||||
f(not not a) # SIM208
|
||||
|
||||
if 1 + (not (not a)): # SIM208
|
||||
pass
|
||||
|
||||
@@ -6,6 +6,7 @@ a = True if b + c else False # SIM210
|
||||
|
||||
a = False if b else True # OK
|
||||
|
||||
|
||||
def f():
|
||||
# OK
|
||||
def bool():
|
||||
|
||||
@@ -42,3 +42,113 @@ if False and f() and a and g() and b: # OK
|
||||
|
||||
if a and False and f() and b and g(): # OK
|
||||
pass
|
||||
|
||||
|
||||
a or "" or True # SIM222
|
||||
|
||||
a or "foo" or True or "bar" # SIM222
|
||||
|
||||
a or 0 or True # SIM222
|
||||
|
||||
a or 1 or True or 2 # SIM222
|
||||
|
||||
a or 0.0 or True # SIM222
|
||||
|
||||
a or 0.1 or True or 0.2 # SIM222
|
||||
|
||||
a or [] or True # SIM222
|
||||
|
||||
a or list([]) or True # SIM222
|
||||
|
||||
a or [1] or True or [2] # SIM222
|
||||
|
||||
a or list([1]) or True or list([2]) # SIM222
|
||||
|
||||
a or {} or True # SIM222
|
||||
|
||||
a or dict() or True # SIM222
|
||||
|
||||
a or {1: 1} or True or {2: 2} # SIM222
|
||||
|
||||
a or dict({1: 1}) or True or dict({2: 2}) # SIM222
|
||||
|
||||
a or set() or True # SIM222
|
||||
|
||||
a or set(set()) or True # SIM222
|
||||
|
||||
a or {1} or True or {2} # SIM222
|
||||
|
||||
a or set({1}) or True or set({2}) # SIM222
|
||||
|
||||
a or () or True # SIM222
|
||||
|
||||
a or tuple(()) or True # SIM222
|
||||
|
||||
a or (1,) or True or (2,) # SIM222
|
||||
|
||||
a or tuple((1,)) or True or tuple((2,)) # SIM222
|
||||
|
||||
a or frozenset() or True # SIM222
|
||||
|
||||
a or frozenset(frozenset()) or True # SIM222
|
||||
|
||||
a or frozenset({1}) or True or frozenset({2}) # SIM222
|
||||
|
||||
a or frozenset(frozenset({1})) or True or frozenset(frozenset({2})) # SIM222
|
||||
|
||||
|
||||
# Inside test `a` is simplified.
|
||||
|
||||
bool(a or [1] or True or [2]) # SIM222
|
||||
|
||||
assert a or [1] or True or [2] # SIM222
|
||||
|
||||
if (a or [1] or True or [2]) and (a or [1] or True or [2]): # SIM222
|
||||
pass
|
||||
|
||||
0 if a or [1] or True or [2] else 1 # SIM222
|
||||
|
||||
while a or [1] or True or [2]: # SIM222
|
||||
pass
|
||||
|
||||
[
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a or [1] or True or [2] # SIM222
|
||||
if b or [1] or True or [2] # SIM222
|
||||
]
|
||||
|
||||
{
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a or [1] or True or [2] # SIM222
|
||||
if b or [1] or True or [2] # SIM222
|
||||
}
|
||||
|
||||
{
|
||||
0: 0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a or [1] or True or [2] # SIM222
|
||||
if b or [1] or True or [2] # SIM222
|
||||
}
|
||||
|
||||
(
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a or [1] or True or [2] # SIM222
|
||||
if b or [1] or True or [2] # SIM222
|
||||
)
|
||||
|
||||
# Outside test `a` is not simplified.
|
||||
|
||||
a or [1] or True or [2] # SIM222
|
||||
|
||||
if (a or [1] or True or [2]) == (a or [1]): # SIM222
|
||||
pass
|
||||
|
||||
if f(a or [1] or True or [2]): # SIM222
|
||||
pass
|
||||
|
||||
@@ -37,3 +37,113 @@ if True or f() or a or g() or b: # OK
|
||||
|
||||
if a or True or f() or b or g(): # OK
|
||||
pass
|
||||
|
||||
|
||||
a and "" and False # SIM223
|
||||
|
||||
a and "foo" and False and "bar" # SIM223
|
||||
|
||||
a and 0 and False # SIM223
|
||||
|
||||
a and 1 and False and 2 # SIM223
|
||||
|
||||
a and 0.0 and False # SIM223
|
||||
|
||||
a and 0.1 and False and 0.2 # SIM223
|
||||
|
||||
a and [] and False # SIM223
|
||||
|
||||
a and list([]) and False # SIM223
|
||||
|
||||
a and [1] and False and [2] # SIM223
|
||||
|
||||
a and list([1]) and False and list([2]) # SIM223
|
||||
|
||||
a and {} and False # SIM223
|
||||
|
||||
a and dict() and False # SIM223
|
||||
|
||||
a and {1: 1} and False and {2: 2} # SIM223
|
||||
|
||||
a and dict({1: 1}) and False and dict({2: 2}) # SIM223
|
||||
|
||||
a and set() and False # SIM223
|
||||
|
||||
a and set(set()) and False # SIM223
|
||||
|
||||
a and {1} and False and {2} # SIM223
|
||||
|
||||
a and set({1}) and False and set({2}) # SIM223
|
||||
|
||||
a and () and False # SIM222
|
||||
|
||||
a and tuple(()) and False # SIM222
|
||||
|
||||
a and (1,) and False and (2,) # SIM222
|
||||
|
||||
a and tuple((1,)) and False and tuple((2,)) # SIM222
|
||||
|
||||
a and frozenset() and False # SIM222
|
||||
|
||||
a and frozenset(frozenset()) and False # SIM222
|
||||
|
||||
a and frozenset({1}) and False and frozenset({2}) # SIM222
|
||||
|
||||
a and frozenset(frozenset({1})) and False and frozenset(frozenset({2})) # SIM222
|
||||
|
||||
|
||||
# Inside test `a` is simplified.
|
||||
|
||||
bool(a and [] and False and []) # SIM223
|
||||
|
||||
assert a and [] and False and [] # SIM223
|
||||
|
||||
if (a and [] and False and []) or (a and [] and False and []): # SIM223
|
||||
pass
|
||||
|
||||
0 if a and [] and False and [] else 1 # SIM222
|
||||
|
||||
while a and [] and False and []: # SIM223
|
||||
pass
|
||||
|
||||
[
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a and [] and False and [] # SIM223
|
||||
if b and [] and False and [] # SIM223
|
||||
]
|
||||
|
||||
{
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a and [] and False and [] # SIM223
|
||||
if b and [] and False and [] # SIM223
|
||||
}
|
||||
|
||||
{
|
||||
0: 0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a and [] and False and [] # SIM223
|
||||
if b and [] and False and [] # SIM223
|
||||
}
|
||||
|
||||
(
|
||||
0
|
||||
for a in range(10)
|
||||
for b in range(10)
|
||||
if a and [] and False and [] # SIM223
|
||||
if b and [] and False and [] # SIM223
|
||||
)
|
||||
|
||||
# Outside test `a` is not simplified.
|
||||
|
||||
a and [] and False and [] # SIM223
|
||||
|
||||
if (a and [] and False and []) == (a and []): # SIM223
|
||||
pass
|
||||
|
||||
if f(a and [] and False and []): # SIM223
|
||||
pass
|
||||
|
||||
@@ -31,3 +31,6 @@ typing.TypedDict.anything()
|
||||
# import aliases are resolved
|
||||
import typing as totally_not_typing
|
||||
totally_not_typing.TypedDict
|
||||
|
||||
# relative imports are respected
|
||||
from .typing import TypedDict
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# module members cannot be imported with that syntax
|
||||
import typing.TypedDict
|
||||
|
||||
# we don't track reassignments
|
||||
import typing, other
|
||||
typing = other
|
||||
typing.TypedDict()
|
||||
|
||||
# yet another false positive
|
||||
def foo(typing):
|
||||
typing.TypedDict()
|
||||
8
crates/ruff/resources/test/fixtures/flake8_todos/TD001.py
vendored
Normal file
8
crates/ruff/resources/test/fixtures/flake8_todos/TD001.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# T001 - accepted
|
||||
# TODO (evanrittenhouse): this is a valid TODO
|
||||
# SOME_OTHER_TAG: this is impossible to determine
|
||||
# this is not a TODO
|
||||
|
||||
# T001 - errors
|
||||
# XXX (evanrittenhouse): this is not fine
|
||||
# FIXME (evanrittenhouse): this is not fine
|
||||
7
crates/ruff/resources/test/fixtures/flake8_todos/TD002.py
vendored
Normal file
7
crates/ruff/resources/test/fixtures/flake8_todos/TD002.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# T002 - accepted
|
||||
# TODO (evanrittenhouse): this has an author
|
||||
# TODO(evanrittenhouse): this also has an author
|
||||
# T002 - errors
|
||||
# TODO: this has no author
|
||||
# FIXME: neither does this
|
||||
# TODO : and neither does this
|
||||
29
crates/ruff/resources/test/fixtures/flake8_todos/TD003.py
vendored
Normal file
29
crates/ruff/resources/test/fixtures/flake8_todos/TD003.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# TDO003 - accepted
|
||||
# TODO: this comment has a link
|
||||
# https://github.com/charliermarsh/ruff/issues/3870
|
||||
|
||||
# TODO: this comment has an issue
|
||||
# TDO-3870
|
||||
|
||||
# TDO003 - errors
|
||||
# TODO: this comment has no
|
||||
# link after it
|
||||
|
||||
# TODO: here's a TODO with no link after it
|
||||
def foo(x):
|
||||
return x
|
||||
|
||||
# TODO: here's a TODO on the last line with no link
|
||||
# Here's more content.
|
||||
# TDO-3870
|
||||
|
||||
# TODO: here's a TODO on the last line with no link
|
||||
# Here's more content, with a space.
|
||||
|
||||
# TDO-3870
|
||||
|
||||
# TODO: here's a TODO without an issue link
|
||||
# TODO: followed by a new TODO with an issue link
|
||||
# TDO-3870
|
||||
|
||||
# TODO: here's a TODO on the last line with no link
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user