Compare commits
240 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa97a092bd | ||
|
|
685c242761 | ||
|
|
b540407b74 | ||
|
|
3a5fbd6d74 | ||
|
|
227679b5cb | ||
|
|
c2750a59ab | ||
|
|
2a4d6ab3b2 | ||
|
|
7a80bcec58 | ||
|
|
297749a3a8 | ||
|
|
8955e32b5c | ||
|
|
cd192eddf9 | ||
|
|
675227db5c | ||
|
|
a65c6806a6 | ||
|
|
6c576872d4 | ||
|
|
9858df1ac9 | ||
|
|
7fb7268e8a | ||
|
|
0f78f27713 | ||
|
|
12a6fc7041 | ||
|
|
d2988043af | ||
|
|
cc8b13d3a7 | ||
|
|
1e081cf9a6 | ||
|
|
841bcf1cdd | ||
|
|
7062d1db16 | ||
|
|
8b561313aa | ||
|
|
cfa2924664 | ||
|
|
a3aeec6377 | ||
|
|
b983d5eb3f | ||
|
|
bb3bb24b59 | ||
|
|
872829ca72 | ||
|
|
2383228709 | ||
|
|
952307d39d | ||
|
|
024caca233 | ||
|
|
08ec11a31e | ||
|
|
bd05a8a74d | ||
|
|
229f1c34cb | ||
|
|
a7f3532395 | ||
|
|
3349ceb969 | ||
|
|
da1f83fe32 | ||
|
|
0a9d259f9c | ||
|
|
130e733023 | ||
|
|
ff2c0dd491 | ||
|
|
dfe1cad928 | ||
|
|
ffad0bcdaa | ||
|
|
bc869d4f52 | ||
|
|
a3de791f0a | ||
|
|
d9dfec30eb | ||
|
|
3f04def3a5 | ||
|
|
98177754de | ||
|
|
8d5374762c | ||
|
|
bad6bdda1f | ||
|
|
a5d302fcbf | ||
|
|
bced58ce40 | ||
|
|
10e252e2fb | ||
|
|
4dead7541f | ||
|
|
fea1af5a63 | ||
|
|
c0ad875339 | ||
|
|
8437399496 | ||
|
|
074f5634a5 | ||
|
|
694d41897a | ||
|
|
e1ebd9130d | ||
|
|
fc8ca6edd2 | ||
|
|
709dba2e71 | ||
|
|
d1c48016eb | ||
|
|
348a38d261 | ||
|
|
22e6778e17 | ||
|
|
30c71dc59a | ||
|
|
5d8591fec4 | ||
|
|
673aa6e90f | ||
|
|
51fe9f7d4b | ||
|
|
d7767b2bad | ||
|
|
40d3b40c14 | ||
|
|
376ef929b1 | ||
|
|
8828e12283 | ||
|
|
f13633cc9f | ||
|
|
889c05c87e | ||
|
|
bbbc44336e | ||
|
|
d216b2aaa8 | ||
|
|
367cc43c42 | ||
|
|
b5b26d5a3e | ||
|
|
dedf8aa5cc | ||
|
|
eb42ce9319 | ||
|
|
cdbe2ee496 | ||
|
|
d1288dc2b1 | ||
|
|
3bcffb5bdd | ||
|
|
98209be8aa | ||
|
|
a03fa93c3a | ||
|
|
4de3882088 | ||
|
|
3a98b68dc0 | ||
|
|
7e291e542d | ||
|
|
6f649d6579 | ||
|
|
508bc605a5 | ||
|
|
ffdf6e35e6 | ||
|
|
886992c6c2 | ||
|
|
187104e396 | ||
|
|
3ed539d50e | ||
|
|
4a70a4c323 | ||
|
|
310f13c7db | ||
|
|
2168404fc2 | ||
|
|
a032b66c2e | ||
|
|
af5f7dbd83 | ||
|
|
8066607ea3 | ||
|
|
0ed9fccce9 | ||
|
|
074a343a63 | ||
|
|
c7e09b54b0 | ||
|
|
67d1f74587 | ||
|
|
1c79dff3bd | ||
|
|
f5f09b489b | ||
|
|
061495a9eb | ||
|
|
470e1c1754 | ||
|
|
16be691712 | ||
|
|
270015865b | ||
|
|
ccfa9d5b20 | ||
|
|
2261e194a0 | ||
|
|
cd6413ca09 | ||
|
|
c65585e14a | ||
|
|
d2a6ed7be6 | ||
|
|
16e2dae0c2 | ||
|
|
e8ba9c9e21 | ||
|
|
d285f5c90a | ||
|
|
386ca7c9a1 | ||
|
|
40c5abf16e | ||
|
|
7e7aec7d74 | ||
|
|
4b5538f74e | ||
|
|
36d134fd41 | ||
|
|
0b7d6b9097 | ||
|
|
994e2e0903 | ||
|
|
bc79f540e4 | ||
|
|
3a78b59314 | ||
|
|
5f83851329 | ||
|
|
484ce7b8fc | ||
|
|
1c75071136 | ||
|
|
51bca19c1d | ||
|
|
a8a312e862 | ||
|
|
33c31cda27 | ||
|
|
cd9fbeb560 | ||
|
|
84e96cdcd9 | ||
|
|
248590224a | ||
|
|
bbc55cdb04 | ||
|
|
2792439eac | ||
|
|
0694aee1b6 | ||
|
|
a17b5c134a | ||
|
|
42f61535b5 | ||
|
|
1c01b3c934 | ||
|
|
39b9a1637f | ||
|
|
2c692e3acf | ||
|
|
24add5f56c | ||
|
|
0b7736ad79 | ||
|
|
eef85067c8 | ||
|
|
da98fab4ae | ||
|
|
0f37a98d91 | ||
|
|
f38624824d | ||
|
|
159422071e | ||
|
|
6eaacf96be | ||
|
|
eb15371453 | ||
|
|
198b301baf | ||
|
|
c8c575dd43 | ||
|
|
6e54cd8233 | ||
|
|
a688a237d7 | ||
|
|
bda2a0007a | ||
|
|
32d165b7ad | ||
|
|
ac79bf4ee9 | ||
|
|
376eab3a53 | ||
|
|
08be7bd285 | ||
|
|
f5241451d8 | ||
|
|
c9fe0708cb | ||
|
|
09f8c487ea | ||
|
|
1e7233a8eb | ||
|
|
f967f344fc | ||
|
|
095f005bf4 | ||
|
|
0f04aa2a5f | ||
|
|
ad7ba77fff | ||
|
|
77d43795f8 | ||
|
|
4357f2be0f | ||
|
|
e5c1f95545 | ||
|
|
227ff62a4e | ||
|
|
d8e4902516 | ||
|
|
e66739884f | ||
|
|
5fd827545b | ||
|
|
c1ddcb8a60 | ||
|
|
48a317d5f6 | ||
|
|
74e18b6cff | ||
|
|
21d02cd51f | ||
|
|
049e77b939 | ||
|
|
b9bfb81e36 | ||
|
|
2d4fae45d9 | ||
|
|
726adb7efc | ||
|
|
dbdfdeb0e1 | ||
|
|
1c41789c2a | ||
|
|
2f9de335db | ||
|
|
ba61bb6a6c | ||
|
|
17ab71ff75 | ||
|
|
4ad4e3e091 | ||
|
|
6ced5122e4 | ||
|
|
7d55b417f7 | ||
|
|
f0e0efc46f | ||
|
|
1efa2e07ad | ||
|
|
df3932f750 | ||
|
|
817d0b4902 | ||
|
|
ffd8e958fc | ||
|
|
ed33b75bad | ||
|
|
262e768fd3 | ||
|
|
bc3a9ce003 | ||
|
|
48005d87f8 | ||
|
|
e37e9c2ca3 | ||
|
|
8fde63b323 | ||
|
|
97338e4cd6 | ||
|
|
9645790a8b | ||
|
|
18800c6884 | ||
|
|
fd638a2e54 | ||
|
|
fa1459d56e | ||
|
|
d93c5811ea | ||
|
|
06e426f509 | ||
|
|
6eb014b3b2 | ||
|
|
d9fd78d907 | ||
|
|
37df07d2e0 | ||
|
|
d5c65b5f1b | ||
|
|
cdc4e86158 | ||
|
|
50ec6d3b0f | ||
|
|
a6eb60cdd5 | ||
|
|
90c04b9cff | ||
|
|
b701cca779 | ||
|
|
ce8953442d | ||
|
|
7d4e513a82 | ||
|
|
35f7f7b66d | ||
|
|
6e02405bd6 | ||
|
|
b657468346 | ||
|
|
f72ed255e5 | ||
|
|
7e9dea0027 | ||
|
|
9545958ad8 | ||
|
|
41faa335d1 | ||
|
|
4cfa350112 | ||
|
|
41f163fc8d | ||
|
|
d21dd994e6 | ||
|
|
6f5a6b8c8b | ||
|
|
35606d7b05 | ||
|
|
3ad257cfea | ||
|
|
b39f960cd1 | ||
|
|
c297d46899 | ||
|
|
d6a100028c | ||
|
|
35d4e03f2a |
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
|
||||
crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
|
||||
|
||||
ruff.schema.json linguist-generated=true text=auto eol=lf
|
||||
91
.github/workflows/ci.yaml
vendored
91
.github/workflows/ci.yaml
vendored
@@ -17,20 +17,6 @@ env:
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
cargo-build:
|
||||
name: "cargo build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo build --all
|
||||
- run: ./target/debug/ruff_dev generate-all
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --exit-code -- README.md ruff.schema.json
|
||||
|
||||
cargo-fmt:
|
||||
name: "cargo fmt"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -61,7 +47,7 @@ jobs:
|
||||
rustup component add clippy
|
||||
rustup target add wasm32-unknown-unknown
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
- run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
|
||||
cargo-test:
|
||||
strategy:
|
||||
@@ -93,6 +79,30 @@ jobs:
|
||||
env:
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug/ruff
|
||||
|
||||
|
||||
cargo-test-wasm:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo test (wasm)"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "npm"
|
||||
cache-dependency-path: playground/package-lock.json
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: "Run wasm-pack"
|
||||
run: |
|
||||
cd crates/ruff_wasm
|
||||
wasm-pack test --node
|
||||
|
||||
scripts:
|
||||
name: "test scripts"
|
||||
@@ -109,21 +119,6 @@ jobs:
|
||||
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
|
||||
- run: cargo check
|
||||
|
||||
maturin-build:
|
||||
name: "maturin build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- run: pip install maturin
|
||||
- run: maturin build -b bin
|
||||
- run: python scripts/transform_readme.py --target pypi
|
||||
|
||||
typos:
|
||||
name: "spell check"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -132,3 +127,39 @@ jobs:
|
||||
- uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
|
||||
ecosystem:
|
||||
name: "ecosystem"
|
||||
runs-on: ubuntu-latest
|
||||
needs: cargo-test
|
||||
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: actions/download-artifact@v3
|
||||
id: ruff-target
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
name: ruff
|
||||
branch: ${{ github.event.pull_request.base_ref }}
|
||||
check_artifacts: true
|
||||
- name: Run ecosystem check
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
|
||||
scripts/check_ecosystem.py ruff ${{ steps.ruff-target.outputs.download-path }}/ruff | tee ecosystem-result
|
||||
|
||||
echo ${{ github.event.number }} > pr-number
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ecosystem-result
|
||||
path: |
|
||||
ecosystem-result
|
||||
pr-number
|
||||
|
||||
31
.github/workflows/ecosystem-comment.yaml
vendored
Normal file
31
.github/workflows/ecosystem-comment.yaml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [CI]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
id: download-result
|
||||
with:
|
||||
name: ecosystem-result
|
||||
workflow: ci.yaml
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
if_no_artifact_found: ignore
|
||||
- if: steps.download-result.outputs.found_artifact
|
||||
id: result
|
||||
run: |
|
||||
echo "pr-number=$(<pr-number)" >> $GITHUB_OUTPUT
|
||||
- name: Create comment
|
||||
if: steps.download-result.outputs.found_artifact
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
pr_number: ${{ steps.result.outputs.pr-number }}
|
||||
filePath: ecosystem-result
|
||||
comment_tag: ecosystem-results
|
||||
2
.github/workflows/playground.yaml
vendored
2
.github/workflows/playground.yaml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
- name: "Run wasm-pack"
|
||||
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff
|
||||
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff_wasm
|
||||
- name: "Install Node dependencies"
|
||||
run: npm ci
|
||||
working-directory: playground
|
||||
|
||||
@@ -5,6 +5,14 @@ repos:
|
||||
hooks:
|
||||
- id: validate-pyproject
|
||||
|
||||
- repo: https://github.com/executablebooks/mdformat
|
||||
rev: 0.7.16
|
||||
hooks:
|
||||
- id: mdformat
|
||||
additional_dependencies:
|
||||
- mdformat-black
|
||||
- black==23.1.0 # Must be the latest version of Black
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.33.0
|
||||
hooks:
|
||||
@@ -13,7 +21,6 @@ repos:
|
||||
- --disable
|
||||
- MD013 # line-length
|
||||
- MD033 # no-inline-html
|
||||
- MD041 # first-line-h1
|
||||
- --
|
||||
|
||||
- repo: local
|
||||
@@ -30,7 +37,7 @@ repos:
|
||||
pass_filenames: false
|
||||
- id: ruff
|
||||
name: ruff
|
||||
entry: cargo run -- --no-cache --fix
|
||||
entry: cargo run -p ruff_cli -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
|
||||
language: rust
|
||||
types_or: [python, pyi]
|
||||
require_serial: true
|
||||
@@ -46,5 +53,16 @@ repos:
|
||||
pass_filenames: false
|
||||
exclude: target
|
||||
|
||||
# Black
|
||||
- repo: https://github.com/psf/black
|
||||
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]
|
||||
|
||||
@@ -20,8 +20,7 @@ the intention of adding a stable public API in the future.
|
||||
### `select`, `extend-select`, `ignore`, and `extend-ignore` have new semantics ([#2312](https://github.com/charliermarsh/ruff/pull/2312))
|
||||
|
||||
Previously, the interplay between `select` and its related options could lead to unexpected
|
||||
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore
|
||||
ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
|
||||
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
|
||||
examples.)
|
||||
|
||||
When Ruff determines the enabled rule set, it has to reconcile `select` and `ignore` from a variety
|
||||
@@ -74,7 +73,7 @@ ruff rule E402 --format json # Works! (And preferred.)
|
||||
This change is largely backwards compatible -- most users should experience
|
||||
no change in behavior. However, please note the following exceptions:
|
||||
|
||||
* Subcommands will now fail when invoked with unsupported arguments, instead
|
||||
- Subcommands will now fail when invoked with unsupported arguments, instead
|
||||
of silently ignoring them. For example, the following will now fail:
|
||||
|
||||
```console
|
||||
@@ -83,16 +82,16 @@ no change in behavior. However, please note the following exceptions:
|
||||
|
||||
(the `clean` command doesn't support `--respect-gitignore`.)
|
||||
|
||||
* The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
|
||||
- The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
|
||||
For example, prior to this release, running `ruff rule` would run `ruff` over a file or
|
||||
directory called `rule`. Now, `ruff rule` would invoke the `rule` subcommand. This should
|
||||
only impact projects with files or directories named `rule`, `check`, `explain`, `clean`,
|
||||
or `generate-shell-completion`.
|
||||
|
||||
* Scripts that invoke ruff should supply `--` before any positional arguments.
|
||||
- Scripts that invoke ruff should supply `--` before any positional arguments.
|
||||
(The semantics of `ruff -- <arg>` have not changed.)
|
||||
|
||||
* `--explain` previously treated `--format grouped` as a synonym for `--format text`.
|
||||
- `--explain` previously treated `--format grouped` as a synonym for `--format text`.
|
||||
This is no longer supported; instead, use `--format text`.
|
||||
|
||||
## 0.0.226
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
* [Our Pledge](#our-pledge)
|
||||
* [Our Standards](#our-standards)
|
||||
* [Enforcement Responsibilities](#enforcement-responsibilities)
|
||||
* [Scope](#scope)
|
||||
* [Enforcement](#enforcement)
|
||||
* [Enforcement Guidelines](#enforcement-guidelines)
|
||||
* [1. Correction](#1-correction)
|
||||
* [2. Warning](#2-warning)
|
||||
* [3. Temporary Ban](#3-temporary-ban)
|
||||
* [4. Permanent Ban](#4-permanent-ban)
|
||||
* [Attribution](#attribution)
|
||||
- [Our Pledge](#our-pledge)
|
||||
- [Our Standards](#our-standards)
|
||||
- [Enforcement Responsibilities](#enforcement-responsibilities)
|
||||
- [Scope](#scope)
|
||||
- [Enforcement](#enforcement)
|
||||
- [Enforcement Guidelines](#enforcement-guidelines)
|
||||
- [1. Correction](#1-correction)
|
||||
- [2. Warning](#2-warning)
|
||||
- [3. Temporary Ban](#3-temporary-ban)
|
||||
- [4. Permanent Ban](#4-permanent-ban)
|
||||
- [Attribution](#attribution)
|
||||
|
||||
## Our Pledge
|
||||
|
||||
@@ -29,23 +29,23 @@ diverse, inclusive, and healthy community.
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
@@ -132,7 +132,7 @@ version 2.0, available [here](https://www.contributor-covenant.org/version/2/0/c
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the [FAQ](https://www.contributor-covenant.org/faq).
|
||||
Translations are available [here](https://www.contributor-covenant.org/translations).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.
|
||||
|
||||
* [The Basics](#the-basics)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Development](#development)
|
||||
* [Project Structure](#project-structure)
|
||||
* [Example: Adding a new lint rule](#example-adding-a-new-lint-rule)
|
||||
* [Rule naming convention](#rule-naming-convention)
|
||||
* [Example: Adding a new configuration option](#example-adding-a-new-configuration-option)
|
||||
* [MkDocs](#mkdocs)
|
||||
* [Release Process](#release-process)
|
||||
* [Benchmarks](#benchmarks)
|
||||
- [The Basics](#the-basics)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Development](#development)
|
||||
- [Project Structure](#project-structure)
|
||||
- [Example: Adding a new lint rule](#example-adding-a-new-lint-rule)
|
||||
- [Rule naming convention](#rule-naming-convention)
|
||||
- [Example: Adding a new configuration option](#example-adding-a-new-configuration-option)
|
||||
- [MkDocs](#mkdocs)
|
||||
- [Release Process](#release-process)
|
||||
- [Benchmarks](#benchmarks)
|
||||
|
||||
## The Basics
|
||||
|
||||
@@ -29,13 +29,10 @@ If you're looking for a place to start, we recommend implementing a new lint rul
|
||||
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
|
||||
existing Python plugins, which can be used as a reference implementation.
|
||||
|
||||
As a concrete example: consider taking on one of the rules from the [`tryceratops`](https://github.com/charliermarsh/ruff/issues/2056)
|
||||
plugin, and looking to the originating [Python source](https://github.com/guilatrova/tryceratops)
|
||||
As a concrete example: consider taking on one of the rules from the [`flake8-pyi`](https://github.com/charliermarsh/ruff/issues/848)
|
||||
plugin, and looking to the originating [Python source](https://github.com/PyCQA/flake8-pyi)
|
||||
for guidance.
|
||||
|
||||
Alternatively, we've started work on the [`flake8-pyi`](https://github.com/charliermarsh/ruff/issues/848)
|
||||
plugin (see the [Python source](https://github.com/PyCQA/flake8-pyi)) -- another good place to start.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Ruff is written in Rust. You'll need to install the
|
||||
@@ -52,16 +49,16 @@ cargo install cargo-insta
|
||||
After cloning the repository, run Ruff locally with:
|
||||
|
||||
```shell
|
||||
cargo run check /path/to/file.py --no-cache
|
||||
cargo run -p ruff_cli -- check /path/to/file.py --no-cache
|
||||
```
|
||||
|
||||
Prior to opening a pull request, ensure that your code has been auto-formatted,
|
||||
and that it passes both the lint and test validation checks:
|
||||
|
||||
```shell
|
||||
cargo fmt --all # Auto-formatting...
|
||||
cargo fmt # Auto-formatting...
|
||||
cargo clippy --fix --workspace --all-targets --all-features # Linting...
|
||||
cargo test --all # Testing...
|
||||
cargo test # Testing...
|
||||
```
|
||||
|
||||
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
|
||||
@@ -94,31 +91,31 @@ The vast majority of the code, including all lint rules, lives in the `ruff` cra
|
||||
|
||||
At time of writing, the repository includes the following crates:
|
||||
|
||||
* `crates/ruff`: library crate containing all lint rules and the core logic for running them.
|
||||
* `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
|
||||
* `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g., `cargo dev generate-all`).
|
||||
* `crates/ruff_macros`: library crate containing macros used by Ruff.
|
||||
* `crates/ruff_python`: library crate implementing Python-specific functionality (e.g., lists of standard library modules by versionb).
|
||||
* `crates/flake8_to_ruff`: binary crate for generating Ruff configuration from Flake8 configuration.
|
||||
- `crates/ruff`: library crate containing all lint rules and the core logic for running them.
|
||||
- `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
|
||||
- `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g., `cargo dev generate-all`).
|
||||
- `crates/ruff_macros`: library crate containing macros used by Ruff.
|
||||
- `crates/ruff_python`: library crate implementing Python-specific functionality (e.g., lists of standard library modules by versionb).
|
||||
- `crates/flake8_to_ruff`: binary crate for generating Ruff configuration from Flake8 configuration.
|
||||
|
||||
### Example: Adding a new lint rule
|
||||
|
||||
At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
|
||||
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention).
|
||||
2. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
|
||||
3. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
|
||||
4. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
|
||||
5. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
|
||||
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
|
||||
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).
|
||||
6. Add a test fixture.
|
||||
7. Update the generated files (documentation and generated code).
|
||||
1. Add a test fixture.
|
||||
1. Update the generated files (documentation and generated code).
|
||||
|
||||
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 `define_violation!`, along with a function that creates the violation
|
||||
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.)
|
||||
|
||||
@@ -135,10 +132,10 @@ contain a variety of violations and non-violations designed to evaluate and demo
|
||||
of your lint rule.
|
||||
|
||||
Run `cargo dev generate-all` to generate the code for your new fixture. Then run Ruff
|
||||
locally with (e.g.) `cargo run check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
|
||||
locally with (e.g.) `cargo run -p ruff_cli -- check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
|
||||
|
||||
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
|
||||
`test_case` macro in the relevant `crates/ruff/src/[linter]/mod.rs` file. Then, run `cargo test --all`.
|
||||
`test_case` macro in the relevant `crates/ruff/src/[linter]/mod.rs` file. Then, run `cargo test`.
|
||||
Your test will fail, but you'll be prompted to follow-up with `cargo insta review`. Accept the
|
||||
generated snapshot, then commit the snapshot file alongside the rest of your changes.
|
||||
|
||||
@@ -150,11 +147,14 @@ The rule name should make sense when read as "allow _rule-name_" or "allow _rule
|
||||
|
||||
This implies that rule names:
|
||||
|
||||
* should state the bad thing being checked for
|
||||
- should state the bad thing being checked for
|
||||
|
||||
* should not contain instructions on what you what you should use instead
|
||||
- should not contain instructions on what you what you should use instead
|
||||
(these belong in the rule documentation and the `autofix_title` for rules that have autofix)
|
||||
|
||||
When re-implementing rules from other linters, this convention is given more importance than
|
||||
preserving the original rule name.
|
||||
|
||||
### Example: Adding a new configuration option
|
||||
|
||||
Ruff's user-facing settings live in a few different places.
|
||||
@@ -191,13 +191,13 @@ To preview any changes to the documentation locally:
|
||||
pip install -r docs/requirements.txt
|
||||
```
|
||||
|
||||
2. Generate the MkDocs site with:
|
||||
1. Generate the MkDocs site with:
|
||||
|
||||
```shell
|
||||
python scripts/generate_mkdocs.py
|
||||
```
|
||||
|
||||
3. Run the development server with:
|
||||
1. Run the development server with:
|
||||
|
||||
```shell
|
||||
mkdocs serve
|
||||
|
||||
495
Cargo.lock
generated
495
Cargo.lock
generated
@@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Inflector"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
@@ -86,7 +92,7 @@ version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e"
|
||||
dependencies = [
|
||||
"bstr 1.2.0",
|
||||
"bstr 1.3.0",
|
||||
"doc-comment",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
@@ -175,9 +181,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832"
|
||||
checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"once_cell",
|
||||
@@ -283,9 +289,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.6"
|
||||
version = "4.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
|
||||
checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
@@ -298,11 +304,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.1.1"
|
||||
version = "4.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6540eedc41f8a5a76cf3d8d458057dcdf817be4158a55b5f861f7a5483de75"
|
||||
checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -311,26 +317,26 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4160b4a4f72ef58bd766bad27c09e6ef1cc9d82a22f6a0f55d152985a4a48e31"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_fig"
|
||||
version = "4.1.0"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf0c76d8fcf782a1102ccfcd10ca8246e7fdd609c1cd6deddbb96cb638e9bb5c"
|
||||
checksum = "63a06158a72dbb088f864887b4409fd22600ba379f3cee3040f842234cc5c2d0"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.1.0"
|
||||
version = "4.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
||||
checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -421,9 +427,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "console_log"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
|
||||
checksum = "878ad067d4089144a36ee412d665916c665430eb84c0057b9987f424a5d15c03"
|
||||
dependencies = [
|
||||
"log",
|
||||
"web-sys",
|
||||
@@ -549,10 +555,20 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.90"
|
||||
name = "ctor"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8"
|
||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@@ -562,9 +578,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38"
|
||||
checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@@ -577,15 +593,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03"
|
||||
checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263"
|
||||
checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -753,10 +769,10 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.248"
|
||||
version = "0.0.255"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"colored",
|
||||
"configparser",
|
||||
"once_cell",
|
||||
@@ -840,7 +856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr 1.2.0",
|
||||
"bstr 1.3.0",
|
||||
"fnv",
|
||||
"log",
|
||||
"regex",
|
||||
@@ -990,9 +1006,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.26.0"
|
||||
version = "1.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f0f08b46e4379744de2ab67aa8f7de3ffd1da3e275adc41fcc82053ede46ff"
|
||||
checksum = "fea5b3894afe466b4bcf0388630fc15e11938a6074af0cd637c825ba2ec8a099"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
@@ -1024,10 +1040,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.3"
|
||||
name = "is-macro"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
|
||||
checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"pmutil",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"io-lifetimes",
|
||||
@@ -1035,15 +1064,6 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_executable"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
@@ -1059,12 +1079,6 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "joinery"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
@@ -1171,7 +1185,7 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
[[package]]
|
||||
name = "libcst"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=f2f0b7a487a8725d161fe8b3ed73a6758b21e177#f2f0b7a487a8725d161fe8b3ed73a6758b21e177"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=80e4c1399f95e5beb532fdd1e209ad2dbb470438#80e4c1399f95e5beb532fdd1e209ad2dbb470438"
|
||||
dependencies = [
|
||||
"chic",
|
||||
"itertools",
|
||||
@@ -1186,7 +1200,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libcst_derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=f2f0b7a487a8725d161fe8b3ed73a6758b21e177#f2f0b7a487a8725d161fe8b3ed73a6758b21e177"
|
||||
source = "git+https://github.com/charliermarsh/LibCST?rev=80e4c1399f95e5beb532fdd1e209ad2dbb470438#80e4c1399f95e5beb532fdd1e209ad2dbb470438"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -1292,14 +1306,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1348,15 +1362,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom8"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "5.1.0"
|
||||
@@ -1384,7 +1389,6 @@ dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1394,7 +1398,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1426,32 +1429,11 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
@@ -1465,6 +1447,15 @@ version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
@@ -1512,6 +1503,12 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "peg"
|
||||
version = "0.8.1"
|
||||
@@ -1539,6 +1536,18 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739"
|
||||
|
||||
[[package]]
|
||||
name = "pep440_rs"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/konstin/pep440-rs.git?rev=a8fef4ec47f4c25b070b39cdbe6a0b9847e49941#a8fef4ec47f4c25b070b39cdbe6a0b9847e49941"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
@@ -1686,6 +1695,17 @@ dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pmutil"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1726,13 +1746,15 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
name = "pretty_assertions"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
|
||||
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"toml_edit",
|
||||
"ctor",
|
||||
"diff",
|
||||
"output_vt100",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1838,9 +1860,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
@@ -1848,9 +1870,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.2"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
@@ -1910,6 +1932,28 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "result-like"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccc7ce6435c33898517a30e85578cd204cbb696875efb93dec19a2d31294f810"
|
||||
dependencies = [
|
||||
"result-like-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "result-like-derive"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fabf0a2e54f711c68c50d49f648a1a8a37adcb57353f518ac4df374f0788f42"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn-ext",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
@@ -1927,29 +1971,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.248"
|
||||
version = "0.0.255"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bisection",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"colored",
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"criterion",
|
||||
"dirs",
|
||||
"fern",
|
||||
"getrandom",
|
||||
"glob",
|
||||
"globset",
|
||||
"ignore",
|
||||
"imperative",
|
||||
"insta",
|
||||
"is_executable",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"libcst",
|
||||
"log",
|
||||
"natord",
|
||||
@@ -1958,16 +1997,23 @@ dependencies = [
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"path-absolutize",
|
||||
"pathdiff",
|
||||
"pep440_rs",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"result-like",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"ruff_macros",
|
||||
"ruff_python",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"shellexpand",
|
||||
"smallvec",
|
||||
"strum",
|
||||
@@ -1975,15 +2021,23 @@ dependencies = [
|
||||
"test-case",
|
||||
"textwrap",
|
||||
"thiserror",
|
||||
"titlecase",
|
||||
"toml",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cache"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"globset",
|
||||
"itertools",
|
||||
"regex",
|
||||
"ruff_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.0.248"
|
||||
version = "0.0.255"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1993,7 +2047,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"cachedir",
|
||||
"chrono",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete_command",
|
||||
"clearscreen",
|
||||
"colored",
|
||||
@@ -2009,9 +2063,12 @@ dependencies = [
|
||||
"rayon",
|
||||
"regex",
|
||||
"ruff",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"similar",
|
||||
"strum",
|
||||
"textwrap",
|
||||
@@ -2025,13 +2082,15 @@ name = "ruff_dev"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"itertools",
|
||||
"libcst",
|
||||
"once_cell",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"ruff",
|
||||
"ruff_cli",
|
||||
"ruff_diagnostics",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
@@ -2041,6 +2100,15 @@ dependencies = [
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_diagnostics"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ruff_python_ast",
|
||||
"rustpython-parser",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_formatter"
|
||||
version = "0.0.0"
|
||||
@@ -2067,7 +2135,52 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python"
|
||||
name = "ruff_python_ast"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_formatter"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.8",
|
||||
"insta",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"ruff_formatter",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"ruff_testing_macros",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"similar",
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_stdlib"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
@@ -2076,19 +2189,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_formatter"
|
||||
name = "ruff_rustpython"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"insta",
|
||||
"once_cell",
|
||||
"ruff_formatter",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_testing_macros"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2101,6 +2218,25 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_wasm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"log",
|
||||
"ruff",
|
||||
"ruff_python_ast",
|
||||
"ruff_rustpython",
|
||||
"rustpython-parser",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-stemmers"
|
||||
version = "1.2.0"
|
||||
@@ -2146,7 +2282,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=61b48f108982d865524f86624a9d5bc2ae3bccef#61b48f108982d865524f86624a9d5bc2ae3bccef"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-compiler-core",
|
||||
@@ -2155,7 +2291,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=61b48f108982d865524f86624a9d5bc2ae3bccef#61b48f108982d865524f86624a9d5bc2ae3bccef"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"bitflags",
|
||||
@@ -2180,24 +2316,21 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=61b48f108982d865524f86624a9d5bc2ae3bccef#61b48f108982d865524f86624a9d5bc2ae3bccef"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
"bstr 0.2.17",
|
||||
"itertools",
|
||||
"lz4_flex",
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num_enum",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=61b48f108982d865524f86624a9d5bc2ae3bccef#61b48f108982d865524f86624a9d5bc2ae3bccef"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@@ -2212,7 +2345,7 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"rustpython-ast",
|
||||
"rustpython-compiler-core",
|
||||
"thiserror",
|
||||
"serde",
|
||||
"tiny-keccak",
|
||||
"unic-emoji-char",
|
||||
"unic-ucd-ident",
|
||||
@@ -2242,9 +2375,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307"
|
||||
checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
@@ -2254,9 +2387,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9"
|
||||
checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2309,9 +2442,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
|
||||
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
@@ -2468,15 +2601,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-ext"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b86cb2b68c5b3c078cac02588bc23f3c04bb828c5d3aedd17980876ec6a7be6"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
@@ -2532,18 +2674,18 @@ checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "2.2.2"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0"
|
||||
checksum = "679b019fb241da62cc449b33b224d19ebe1c6767b495569765115dd7f7f9fba4"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "2.2.2"
|
||||
name = "test-case-core"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26"
|
||||
checksum = "72dc21b5887f4032c4656502d085dc28f2afbb686f25f216472bb0526f4b1b88"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-error",
|
||||
@@ -2552,6 +2694,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3786898e0be151a96f730fd529b0e8a10f5990fa2a7ea14e37ca27613c05190"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.0"
|
||||
@@ -2658,22 +2813,11 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "titlecase"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38397a8cdb017cfeb48bf6c154d6de975ac69ffeed35980fde199d2ee0842042"
|
||||
dependencies = [
|
||||
"joinery",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.6.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217"
|
||||
checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@@ -2683,24 +2827,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
|
||||
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.18.1"
|
||||
version = "0.19.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
|
||||
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"nom8",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2711,9 +2855,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.30"
|
||||
@@ -2854,9 +3010,11 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "029df4cc8238cefc911704ff8fa210853a0f3bce2694d8f51181dd41ee0f3301"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/youknowone/unicode_names2.git?rev=4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde#4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
@@ -3189,6 +3347,15 @@ version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
@@ -3198,6 +3365,12 @@ dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi-term"
|
||||
version = "0.1.2"
|
||||
|
||||
45
Cargo.toml
45
Cargo.toml
@@ -3,24 +3,45 @@ members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
rust-version = "1.67"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = { version = "1.0.66" }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
anyhow = { version = "1.0.69" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
colored = { version = "2.0.0" }
|
||||
filetime = { version = "0.2.20" }
|
||||
glob = { version = "0.3.1" }
|
||||
globset = { version = "0.4.10" }
|
||||
ignore = { version = "0.4.20" }
|
||||
insta = { version = "1.28.0" }
|
||||
is-macro = { version = "0.2.2" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
regex = { version = "1.6.0" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
|
||||
log = { version = "0.4.17" }
|
||||
once_cell = { version = "1.17.1" }
|
||||
path-absolutize = { version = "3.0.14" }
|
||||
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 = "61b48f108982d865524f86624a9d5bc2ae3bccef" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "61b48f108982d865524f86624a9d5bc2ae3bccef" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
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" }
|
||||
schemars = { version = "0.8.12" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93" }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
similar = { version = "2.2.1" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
toml = { version = "0.6.0" }
|
||||
syn = { version = "1.0.109" }
|
||||
test-case = { version = "3.0.0" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
toml = { version = "0.7.2" }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
609
README.md
609
README.md
@@ -24,16 +24,17 @@ An extremely fast Python linter, written in Rust.
|
||||
<i>Linting the CPython codebase from scratch.</i>
|
||||
</p>
|
||||
|
||||
* ⚡️ 10-100x faster than existing linters
|
||||
* 🐍 Installable via `pip`
|
||||
* 🛠️ `pyproject.toml` support
|
||||
* 📦 Built-in caching, to avoid re-analyzing unchanged files
|
||||
* 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
* 📏 Over [400 built-in rules](https://beta.ruff.rs/docs/rules/) (and growing)
|
||||
* ⚖️ [Near-parity](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
|
||||
* 🔌 Native re-implementations of dozens of Flake8 plugins, like flake8-bugbear
|
||||
* ⌨️ First-party editor integrations for [VS Code](https://github.com/charliermarsh/ruff-vscode) and [more](https://github.com/charliermarsh/ruff-lsp)
|
||||
* 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](#pyprojecttoml-discovery)
|
||||
- ⚡️ 10-100x faster than existing linters
|
||||
- 🐍 Installable via `pip`
|
||||
- 🛠️ `pyproject.toml` support
|
||||
- 🤝 Python 3.11 compatibility
|
||||
- 📦 Built-in caching, to avoid re-analyzing unchanged files
|
||||
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
- 📏 Over [500 built-in rules](https://beta.ruff.rs/docs/rules/)
|
||||
- ⚖️ [Near-parity](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
|
||||
- 🔌 Native re-implementations of dozens of Flake8 plugins, like flake8-bugbear
|
||||
- ⌨️ First-party editor integrations for [VS Code](https://github.com/charliermarsh/ruff-vscode) and [more](https://github.com/charliermarsh/ruff-lsp)
|
||||
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://beta.ruff.rs/docs/configuration/#pyprojecttoml-discovery)
|
||||
|
||||
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
|
||||
functionality behind a single, common interface.
|
||||
@@ -46,11 +47,11 @@ 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)
|
||||
* [SciPy](https://github.com/scipy/scipy)
|
||||
- [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)
|
||||
- [SciPy](https://github.com/scipy/scipy)
|
||||
|
||||
...and many more.
|
||||
|
||||
@@ -96,21 +97,19 @@ developer of [Zulip](https://github.com/zulip/zulip):
|
||||
|
||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||
|
||||
1. [Installation and Usage](#installation-and-usage)
|
||||
2. [Configuration](#configuration)
|
||||
3. [Supported Rules](#supported-rules)
|
||||
4. [Contributing](#contributing)
|
||||
5. [Support](#support)
|
||||
6. [Acknowledgements](#acknowledgements)
|
||||
7. [Who's Using Ruff?](#whos-using-ruff)
|
||||
8. [License](#license)
|
||||
1. [Getting Started](#getting-started)
|
||||
1. [Configuration](#configuration)
|
||||
1. [Rules](#rules)
|
||||
1. [Contributing](#contributing)
|
||||
1. [Support](#support)
|
||||
1. [Acknowledgements](#acknowledgements)
|
||||
1. [Who's Using Ruff?](#whos-using-ruff)
|
||||
1. [License](#license)
|
||||
|
||||
## Installation and Usage
|
||||
## Getting Started
|
||||
|
||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||
|
||||
<!-- Begin section: Installation and Usage -->
|
||||
|
||||
### Installation
|
||||
|
||||
Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||
@@ -119,31 +118,8 @@ Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||
pip install ruff
|
||||
```
|
||||
|
||||
For **macOS Homebrew** and **Linuxbrew** users, Ruff is also available as [`ruff`](https://formulae.brew.sh/formula/ruff) on Homebrew:
|
||||
|
||||
```shell
|
||||
brew install ruff
|
||||
```
|
||||
|
||||
For **Conda** users, Ruff is also available as [`ruff`](https://anaconda.org/conda-forge/ruff) on `conda-forge`:
|
||||
|
||||
```shell
|
||||
conda install -c conda-forge ruff
|
||||
```
|
||||
|
||||
For **Arch Linux** users, Ruff is also available as [`ruff`](https://archlinux.org/packages/community/x86_64/ruff/) on the official repositories:
|
||||
|
||||
```shell
|
||||
pacman -S ruff
|
||||
```
|
||||
|
||||
For **Alpine** users, Ruff is also available as [`ruff`](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/ruff) on the testing repositories:
|
||||
|
||||
```shell
|
||||
apk add ruff
|
||||
```
|
||||
|
||||
[](https://repology.org/project/ruff-python-linter/versions)
|
||||
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||
and with [a variety of other package managers](https://beta.ruff.rs/docs/installation/).
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -156,51 +132,30 @@ ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`
|
||||
ruff check path/to/code/to/file.py # Lint `file.py`
|
||||
```
|
||||
|
||||
You can run Ruff in `--watch` mode to automatically re-run on-change:
|
||||
|
||||
```shell
|
||||
ruff check path/to/code/ --watch
|
||||
```
|
||||
|
||||
Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
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.248'
|
||||
rev: 'v0.0.255'
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
|
||||
Or, to enable autofix:
|
||||
Ruff can also be used as a [VS Code extension](https://github.com/charliermarsh/ruff-vscode) or
|
||||
alongside any other editor through the [Ruff LSP](https://github.com/charliermarsh/ruff-lsp).
|
||||
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.248'
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
```
|
||||
### Configuration
|
||||
|
||||
<!-- End section: Installation and Usage -->
|
||||
|
||||
## Configuration
|
||||
|
||||
<!-- Begin section: Configuration -->
|
||||
|
||||
Ruff can be configured via a `pyproject.toml` file, a `ruff.toml` file, or through the command line.
|
||||
|
||||
For a complete enumeration of the available configuration options, see the
|
||||
[documentation](https://beta.ruff.rs/docs/settings/).
|
||||
|
||||
### Configure via `pyproject.toml`
|
||||
Ruff can be configured through a `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (see:
|
||||
[_Configuration_](https://beta.ruff.rs/docs/configuration/), or [_Settings_](https://beta.ruff.rs/docs/settings/)
|
||||
for a complete list of all configuration options).
|
||||
|
||||
If left unspecified, the default configuration is equivalent to:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Enable Pyflakes `E` and `F` codes by default.
|
||||
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
|
||||
select = ["E", "F"]
|
||||
ignore = []
|
||||
|
||||
@@ -231,7 +186,6 @@ exclude = [
|
||||
"node_modules",
|
||||
"venv",
|
||||
]
|
||||
per-file-ignores = {}
|
||||
|
||||
# Same as Black.
|
||||
line-length = 88
|
||||
@@ -247,428 +201,42 @@ target-version = "py310"
|
||||
max-complexity = 10
|
||||
```
|
||||
|
||||
As an example, the following would configure Ruff to: (1) enforce flake8-bugbear rules, in addition
|
||||
to the defaults; (2) avoid enforcing line-length violations (`E501`); (3) avoid attempting to fix
|
||||
flake8-bugbear (`B`) violations; and (3) ignore import-at-top-of-file violations (`E402`) in
|
||||
`__init__.py` files:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Enable flake8-bugbear (`B`) rules.
|
||||
select = ["E", "F", "B"]
|
||||
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
||||
unfixable = ["B"]
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
[tool.ruff.per-file-ignores]
|
||||
"__init__.py" = ["E402"]
|
||||
"path/to/file.py" = ["E402"]
|
||||
```
|
||||
|
||||
Plugin configurations should be expressed as subsections, e.g.:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Add "Q" to the list of enabled codes.
|
||||
select = ["E", "F", "Q"]
|
||||
|
||||
[tool.ruff.flake8-quotes]
|
||||
docstring-quotes = "double"
|
||||
```
|
||||
|
||||
Ruff mirrors Flake8's rule code system, in which each rule code consists of a one-to-three letter
|
||||
prefix, followed by three digits (e.g., `F401`). The prefix indicates that "source" of the rule
|
||||
(e.g., `F` for Pyflakes, `E` for pycodestyle, `ANN` for flake8-annotations). The set of enabled
|
||||
rules is determined by the `select` and `ignore` options, which support both the full code (e.g.,
|
||||
`F401`) and the prefix (e.g., `F`).
|
||||
|
||||
As a special-case, Ruff also supports the `ALL` code, which enables all rules. Note that some of the
|
||||
pydocstyle rules conflict (e.g., `D203` and `D211`) as they represent alternative docstring
|
||||
formats. Enabling `ALL` without further configuration may result in suboptimal behavior, especially
|
||||
for the pydocstyle plugin.
|
||||
|
||||
If you're wondering how to configure Ruff, here are some **recommended guidelines**:
|
||||
|
||||
* Prefer `select` and `ignore` over `extend-select` and `extend-ignore`, to make your rule set
|
||||
explicit.
|
||||
* Use `ALL` with discretion. Enabling `ALL` will implicitly enable new rules whenever you upgrade.
|
||||
* Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
|
||||
you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear
|
||||
extension.
|
||||
* By default, Ruff's autofix is aggressive. If you find that it's too aggressive for your liking,
|
||||
consider turning off autofix for specific rules or categories (see: [FAQ](https://beta.ruff.rs/docs/faq/#ruff-tried-to-fix-something-but-it-broke-my-code-what-should-i-do)).
|
||||
|
||||
### Configure via `ruff.toml`
|
||||
|
||||
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
|
||||
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the
|
||||
`pyproject.toml` described above would be represented via the following `ruff.toml`:
|
||||
|
||||
```toml
|
||||
# Enable flake8-bugbear (`B`) rules.
|
||||
select = ["E", "F", "B"]
|
||||
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
||||
unfixable = ["B"]
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
[per-file-ignores]
|
||||
"__init__.py" = ["E402"]
|
||||
"path/to/file.py" = ["E402"]
|
||||
```
|
||||
|
||||
For a full list of configurable options, see the [list of all options](https://beta.ruff.rs/docs/settings/).
|
||||
|
||||
### Command-line interface
|
||||
|
||||
Some configuration settings can be provided via the command-line, such as those related to
|
||||
Some configuration options can be provided via the command-line, such as those related to
|
||||
rule enablement and disablement, file discovery, logging level, and more:
|
||||
|
||||
```shell
|
||||
ruff check path/to/code/ --select F401 --select F403 --quiet
|
||||
```
|
||||
|
||||
See `ruff help` for more on Ruff's top-level commands:
|
||||
See `ruff help` for more on Ruff's top-level commands, or `ruff help check` for more on the
|
||||
linting command.
|
||||
|
||||
<!-- Begin auto-generated command help. -->
|
||||
|
||||
```text
|
||||
Ruff: An extremely fast Python linter.
|
||||
|
||||
Usage: ruff [OPTIONS] <COMMAND>
|
||||
|
||||
Commands:
|
||||
check Run Ruff on the given files or directories (default)
|
||||
rule Explain a rule
|
||||
config List or describe the available configuration options
|
||||
linter List all supported upstream linters
|
||||
clean Clear any caches in the current directory and any subdirectories
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
Log levels:
|
||||
-v, --verbose Enable verbose logging
|
||||
-q, --quiet Print lint violations, but nothing else
|
||||
-s, --silent Disable all logging (but still exit with status code "1" upon detecting lint violations)
|
||||
|
||||
For help with a specific command, see: `ruff help <command>`.
|
||||
```
|
||||
|
||||
<!-- End auto-generated command help. -->
|
||||
|
||||
Or `ruff help check` for more on the linting command:
|
||||
|
||||
<!-- Begin auto-generated subcommand help. -->
|
||||
|
||||
```text
|
||||
Run Ruff on the given files or directories (default)
|
||||
|
||||
Usage: ruff check [OPTIONS] [FILES]...
|
||||
|
||||
Arguments:
|
||||
[FILES]... List of files or directories to check
|
||||
|
||||
Options:
|
||||
--fix
|
||||
Attempt to automatically fix lint violations
|
||||
--show-source
|
||||
Show violations with source code
|
||||
--show-fixes
|
||||
Show an enumeration of all autofixed lint violations
|
||||
--diff
|
||||
Avoid writing any fixed files back; instead, output a diff for each changed file to stdout
|
||||
-w, --watch
|
||||
Run in watch mode by re-running whenever files change
|
||||
--fix-only
|
||||
Fix any fixable lint violations, but don't report on leftover violations. Implies `--fix`
|
||||
--format <FORMAT>
|
||||
Output serialization format for violations [env: RUFF_FORMAT=] [possible values: text, json, junit, grouped, github, gitlab, pylint]
|
||||
--target-version <TARGET_VERSION>
|
||||
The minimum Python version that should be supported
|
||||
--config <CONFIG>
|
||||
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
||||
--statistics
|
||||
Show counts for every rule with at least one violation
|
||||
--add-noqa
|
||||
Enable automatic additions of `noqa` directives to failing lines
|
||||
--show-files
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
See the settings Ruff will use to lint a given Python file
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
Rule selection:
|
||||
--select <RULE_CODE>
|
||||
Comma-separated list of rule codes to enable (or ALL, to enable all rules)
|
||||
--ignore <RULE_CODE>
|
||||
Comma-separated list of rule codes to disable
|
||||
--extend-select <RULE_CODE>
|
||||
Like --select, but adds additional rule codes on top of the selected ones
|
||||
--per-file-ignores <PER_FILE_IGNORES>
|
||||
List of mappings from file pattern to code to exclude
|
||||
--fixable <RULE_CODE>
|
||||
List of rule codes to treat as eligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
--unfixable <RULE_CODE>
|
||||
List of rule codes to treat as ineligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
|
||||
File selection:
|
||||
--exclude <FILE_PATTERN> List of paths, used to omit files and/or directories from analysis
|
||||
--extend-exclude <FILE_PATTERN> Like --exclude, but adds additional files and directories on top of those already excluded
|
||||
--respect-gitignore Respect file exclusions via `.gitignore` and other standard ignore files
|
||||
--force-exclude Enforce exclusions, even for paths passed to Ruff directly on the command-line
|
||||
|
||||
Miscellaneous:
|
||||
-n, --no-cache
|
||||
Disable cache reads
|
||||
--isolated
|
||||
Ignore all configuration files
|
||||
--cache-dir <CACHE_DIR>
|
||||
Path to the cache directory [env: RUFF_CACHE_DIR=]
|
||||
--stdin-filename <STDIN_FILENAME>
|
||||
The name of the file when passing it through stdin
|
||||
-e, --exit-zero
|
||||
Exit with status code "0", even upon detecting lint violations
|
||||
--exit-non-zero-on-fix
|
||||
Exit with a non-zero status code if any files were modified via autofix, even if no lint violations remain
|
||||
|
||||
Log levels:
|
||||
-v, --verbose Enable verbose logging
|
||||
-q, --quiet Print lint violations, but nothing else
|
||||
-s, --silent Disable all logging (but still exit with status code "1" upon detecting lint violations)
|
||||
```
|
||||
|
||||
<!-- End auto-generated subcommand help. -->
|
||||
|
||||
### `pyproject.toml` discovery
|
||||
|
||||
Similar to [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
||||
Ruff supports hierarchical configuration, such that the "closest" `pyproject.toml` file in the
|
||||
directory hierarchy is used for every individual file, with all paths in the `pyproject.toml` file
|
||||
(e.g., `exclude` globs, `src` paths) being resolved relative to the directory containing the
|
||||
`pyproject.toml` file.
|
||||
|
||||
There are a few exceptions to these rules:
|
||||
|
||||
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignores any
|
||||
`pyproject.toml` files that lack a `[tool.ruff]` section.
|
||||
2. If a configuration file is passed directly via `--config`, those settings are used for across
|
||||
files. Any relative paths in that configuration file (like `exclude` globs or `src` paths) are
|
||||
resolved relative to the _current working directory_.
|
||||
3. If no `pyproject.toml` file is found in the filesystem hierarchy, Ruff will fall back to using
|
||||
a default configuration. If a user-specific configuration file exists
|
||||
at `${config_dir}/ruff/pyproject.toml`, that file will be used instead of the default
|
||||
configuration, with `${config_dir}` being determined via the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html)
|
||||
crate, and all relative paths being again resolved relative to the _current working directory_.
|
||||
4. Any `pyproject.toml`-supported settings that are provided on the command-line (e.g., via
|
||||
`--select`) will override the settings in _every_ resolved configuration file.
|
||||
|
||||
Unlike [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
||||
Ruff does not merge settings across configuration files; instead, the "closest" configuration file
|
||||
is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff
|
||||
supports an [`extend`](https://beta.ruff.rs/docs/settings#extend) field, which allows you to inherit the settings from another
|
||||
`pyproject.toml` file, like so:
|
||||
|
||||
```toml
|
||||
# Extend the `pyproject.toml` file in the parent directory.
|
||||
extend = "../pyproject.toml"
|
||||
# But use a different line length.
|
||||
line-length = 100
|
||||
```
|
||||
|
||||
All of the above rules apply equivalently to `ruff.toml` files. If Ruff detects both a `ruff.toml`
|
||||
and `pyproject.toml` file, it will defer to the `ruff.toml`.
|
||||
|
||||
### Python file discovery
|
||||
|
||||
When passed a path on the command-line, Ruff will automatically discover all Python files in that
|
||||
path, taking into account the [`exclude`](https://beta.ruff.rs/docs/settings#exclude) and
|
||||
[`extend-exclude`](https://beta.ruff.rs/docs/settings#extend-exclude) settings in each directory's
|
||||
`pyproject.toml` file.
|
||||
|
||||
By default, Ruff will also skip any files that are omitted via `.ignore`, `.gitignore`,
|
||||
`.git/info/exclude`, and global `gitignore` files (see: [`respect-gitignore`](https://beta.ruff.rs/docs/settings#respect-gitignore)).
|
||||
|
||||
Files that are passed to `ruff` directly are always linted, regardless of the above criteria.
|
||||
For example, `ruff check /path/to/excluded/file.py` will always lint `file.py`.
|
||||
|
||||
### Rule resolution
|
||||
|
||||
The set of enabled rules is controlled via the [`select`](https://beta.ruff.rs/docs/settings#select)
|
||||
and [`ignore`](https://beta.ruff.rs/docs/settings#ignore) settings, along with the
|
||||
[`extend-select`](https://beta.ruff.rs/docs/settings#extend-select) and
|
||||
[`extend-ignore`](https://beta.ruff.rs/docs/settings#extend-ignore) modifiers.
|
||||
|
||||
To resolve the enabled rule set, Ruff may need to reconcile `select` and `ignore` from a variety
|
||||
of sources, including the current `pyproject.toml`, any inherited `pyproject.toml` files, and the
|
||||
CLI (e.g., `--select`).
|
||||
|
||||
In those scenarios, Ruff uses the "highest-priority" `select` as the basis for the rule set, and
|
||||
then applies any `extend-select`, `ignore`, and `extend-ignore` adjustments. CLI options are given
|
||||
higher priority than `pyproject.toml` options, and the current `pyproject.toml` file is given higher
|
||||
priority than any inherited `pyproject.toml` files.
|
||||
|
||||
For example, given the following `pyproject.toml` file:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
select = ["E", "F"]
|
||||
ignore = ["F401"]
|
||||
```
|
||||
|
||||
Running `ruff check --select F401` would result in Ruff enforcing `F401`, and no other rules.
|
||||
|
||||
Running `ruff check --extend-select B` would result in Ruff enforcing the `E`, `F`, and `B` rules, with
|
||||
the exception of `F401`.
|
||||
|
||||
### Suppressing errors
|
||||
|
||||
To omit a lint rule entirely, add it to the "ignore" list via [`ignore`](https://beta.ruff.rs/docs/settings#ignore)
|
||||
or [`extend-ignore`](https://beta.ruff.rs/docs/settings#extend-ignore), either on the command-line
|
||||
or in your `pyproject.toml` file.
|
||||
|
||||
To ignore a violation inline, Ruff uses a `noqa` system similar to [Flake8](https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html).
|
||||
To ignore an individual violation, add `# noqa: {code}` to the end of the line, like so:
|
||||
|
||||
```python
|
||||
# Ignore F841.
|
||||
x = 1 # noqa: F841
|
||||
|
||||
# Ignore E741 and F841.
|
||||
i = 1 # noqa: E741, F841
|
||||
|
||||
# Ignore _all_ violations.
|
||||
x = 1 # noqa
|
||||
```
|
||||
|
||||
Note that, for multi-line strings, the `noqa` directive should come at the end of the string, and
|
||||
will apply to the entire string, like so:
|
||||
|
||||
```python
|
||||
"""Lorem ipsum dolor sit amet.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
|
||||
""" # noqa: E501
|
||||
```
|
||||
|
||||
To ignore all violations across an entire file, add `# ruff: noqa` to any line in the file, like so:
|
||||
|
||||
```python
|
||||
# ruff: noqa
|
||||
```
|
||||
|
||||
To ignore a specific rule across an entire file, add `# ruff: noqa: {code}` to any line in the file,
|
||||
like so:
|
||||
|
||||
```python
|
||||
# ruff: noqa: F841
|
||||
```
|
||||
|
||||
Or see the [`per-file-ignores`](https://beta.ruff.rs/docs/settings#per-file-ignores) configuration
|
||||
setting, which enables the same functionality via a `pyproject.toml` file.
|
||||
|
||||
Note that Ruff will also respect Flake8's `# flake8: noqa` directive, and will treat it as
|
||||
equivalent to `# ruff: noqa`.
|
||||
|
||||
#### Automatic error suppression
|
||||
|
||||
Ruff supports several workflows to aid in `noqa` management.
|
||||
|
||||
First, Ruff provides a special rule code, `RUF100`, to enforce that your `noqa` directives are
|
||||
"valid", in that the violations they _say_ they ignore are actually being triggered on that line (and
|
||||
thus suppressed). You can run `ruff check /path/to/file.py --extend-select RUF100` to flag unused `noqa`
|
||||
directives.
|
||||
|
||||
Second, Ruff can _automatically remove_ unused `noqa` directives via its autofix functionality.
|
||||
You can run `ruff check /path/to/file.py --extend-select RUF100 --fix` to automatically remove unused
|
||||
`noqa` directives.
|
||||
|
||||
Third, Ruff can _automatically add_ `noqa` directives to all failing lines. This is useful when
|
||||
migrating a new codebase to Ruff. You can run `ruff check /path/to/file.py --add-noqa` to automatically
|
||||
add `noqa` directives to all failing lines, with the appropriate rule codes.
|
||||
|
||||
#### Action comments
|
||||
|
||||
Ruff respects `isort`'s [action comments](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
||||
(`# isort: skip_file`, `# isort: on`, `# isort: off`, `# isort: skip`, and `# isort: split`), which
|
||||
enable selectively enabling and disabling import sorting for blocks of code and other inline
|
||||
configuration.
|
||||
|
||||
See the [`isort` documentation](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
||||
for more.
|
||||
|
||||
### Exit codes
|
||||
|
||||
By default, Ruff exits with the following status codes:
|
||||
|
||||
* `0` if no violations were found, or if all present violations were fixed automatically.
|
||||
* `1` if violations were found.
|
||||
* `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.
|
||||
|
||||
This convention mirrors that of tools like ESLint, Prettier, and RuboCop.
|
||||
|
||||
Ruff supports two command-line flags that alter its exit code behavior:
|
||||
|
||||
* `--exit-zero` will cause Ruff to exit with a status code of `0` even if violations were found.
|
||||
Note that Ruff will still exit with a status code of `2` if it terminates abnormally.
|
||||
* `--exit-non-zero-on-fix` will cause Ruff to exit with a status code of `1` if violations were
|
||||
found, _even if_ all such violations were fixed automatically. Note that the use of
|
||||
`--exit-non-zero-on-fix` can result in a non-zero exit code even if no violations remain after
|
||||
autofixing.
|
||||
|
||||
### Autocompletion
|
||||
|
||||
Ruff supports autocompletion for most shells. A shell-specific completion script can be generated
|
||||
by `ruff generate-shell-completion <SHELL>`, where `<SHELL>` is one of `bash`, `elvish`, `fig`, `fish`,
|
||||
`powershell`, or `zsh`.
|
||||
|
||||
The exact steps required to enable autocompletion will vary by shell. For example instructions,
|
||||
see the [Poetry](https://python-poetry.org/docs/#enable-tab-completion-for-bash-fish-or-zsh) or
|
||||
[ripgrep](https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#complete) documentation.
|
||||
|
||||
As an example: to enable autocompletion for Zsh, run
|
||||
`ruff generate-shell-completion zsh > ~/.zfunc/_ruff`. Then add the following line to your
|
||||
`~/.zshrc` file, if they're not already present:
|
||||
|
||||
```zsh
|
||||
fpath+=~/.zfunc
|
||||
autoload -Uz compinit && compinit
|
||||
```
|
||||
|
||||
<!-- End section: Configuration -->
|
||||
|
||||
## Supported Rules
|
||||
## Rules
|
||||
|
||||
<!-- Begin section: Rules -->
|
||||
|
||||
Ruff supports over 400 lint rules, many of which are inspired by popular tools like Flake8, isort,
|
||||
pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
|
||||
**Ruff supports over 500 lint rules**, many of which are inspired by popular tools like Flake8,
|
||||
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
|
||||
Rust as a first-party feature.
|
||||
|
||||
By default, Ruff enables Flake8's `E` and `F` rules. Ruff supports all rules from the `F` category,
|
||||
and a [subset](https://beta.ruff.rs/docs/rules/#error-e) of the `E` category, omitting those
|
||||
stylistic rules made obsolete by the use of an autoformatter, like [Black](https://github.com/psf/black).
|
||||
stylistic rules made obsolete by the use of an autoformatter, like
|
||||
[Black](https://github.com/psf/black).
|
||||
|
||||
If you're just getting started with Ruff, **the default rule set is a great place to start**: it
|
||||
catches a wide variety of common errors (like unused imports) with zero configuration.
|
||||
|
||||
<!-- End section: Rules -->
|
||||
|
||||
For a complete enumeration, see the [list of rules](https://beta.ruff.rs/docs/rules/) in the
|
||||
Ruff documentation.
|
||||
For a complete enumeration of the supported rules, see [_Rules_](https://beta.ruff.rs/docs/rules/).
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome and highly appreciated. To get started, check out the
|
||||
[**contributing guidelines**](https://github.com/charliermarsh/ruff/blob/main/CONTRIBUTING.md). You
|
||||
can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||
[**contributing guidelines**](https://beta.ruff.rs/docs/contributing/).
|
||||
|
||||
You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||
|
||||
## Support
|
||||
|
||||
@@ -677,8 +245,6 @@ or feel free to [**open a new one**](https://github.com/charliermarsh/ruff/issue
|
||||
|
||||
You can also ask for help on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||
|
||||
<!-- Begin section: Acknowledgements -->
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Ruff's linter draws on both the APIs and implementation details of many other
|
||||
@@ -701,45 +267,48 @@ Ruff is the beneficiary of a large number of [contributors](https://github.com/c
|
||||
|
||||
Ruff is released under the MIT license.
|
||||
|
||||
<!-- End section: Acknowledgements -->
|
||||
|
||||
## Who's Using Ruff?
|
||||
|
||||
Ruff is used in a number of major open-source projects, 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)
|
||||
* [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)
|
||||
* [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)
|
||||
* [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)
|
||||
* [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.248"
|
||||
version = "0.0.255"
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
ruff = { path = "../ruff", default-features = false }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
colored = { version = "2.0.0" }
|
||||
colored = { workspace = true }
|
||||
configparser = { version = "3.0.2" }
|
||||
once_cell = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
ruff = { path = "../ruff", default-features = false }
|
||||
rustc-hash = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -84,7 +84,7 @@ flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
|
||||
1. Ruff only supports a subset of the Flake configuration options. `flake8-to-ruff` will warn on and
|
||||
ignore unsupported options in the `.flake8` file (or equivalent). (Similarly, Ruff has a few
|
||||
configuration options that don't exist in Flake8.)
|
||||
2. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
|
||||
1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
|
||||
codes from unsupported plugins. (See the [Ruff README](https://github.com/charliermarsh/ruff#user-content-how-does-ruff-compare-to-flake8)
|
||||
for the complete list of supported plugins.)
|
||||
|
||||
|
||||
@@ -46,8 +46,15 @@ fn main() -> Result<()> {
|
||||
.map(|tool| ExternalConfig {
|
||||
black: tool.black.as_ref(),
|
||||
isort: tool.isort.as_ref(),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let external_config = ExternalConfig {
|
||||
project: pyproject
|
||||
.as_ref()
|
||||
.and_then(|pyproject| pyproject.project.as_ref()),
|
||||
..external_config
|
||||
};
|
||||
|
||||
// Create Ruff's pyproject.toml section.
|
||||
let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.248"
|
||||
version = "0.0.255"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
@@ -12,70 +12,66 @@ license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
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_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
bisection = { version = "0.1.0" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cfg-if = { version = "1.0.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
bitflags = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive", "env", "string"] }
|
||||
colored = { version = "2.0.0" }
|
||||
colored = { workspace = true }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
ignore = { version = "0.4.18" }
|
||||
imperative = { version = "1.0.3" }
|
||||
glob = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
ignore = { workspace = true }
|
||||
imperative = { version = "1.0.4" }
|
||||
is-macro = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
libcst = { workspace = true }
|
||||
log = { version = "0.4.17" }
|
||||
log = { workspace = true }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = "0.2.15"
|
||||
num-traits = { version = "0.2.15" }
|
||||
once_cell = { workspace = true }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
path-absolutize = { workspace = true, features = [
|
||||
"once_cell_cache",
|
||||
"use_unix_paths_on_wasm",
|
||||
] }
|
||||
pathdiff = { version = "0.2.1" }
|
||||
pep440_rs = { git = "https://github.com/konstin/pep440-rs.git", features = [
|
||||
"serde",
|
||||
], rev = "a8fef4ec47f4c25b070b39cdbe6a0b9847e49941" }
|
||||
regex = { workspace = true }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python = { path = "../ruff_python" }
|
||||
result-like = { version = "0.4.6" }
|
||||
rustc-hash = { workspace = true }
|
||||
rustpython-common = { workspace = true }
|
||||
rustpython-parser = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { workspace = true }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
shellexpand = { workspace = true }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { workspace = true }
|
||||
strum_macros = { workspace = true }
|
||||
textwrap = { version = "0.16.0" }
|
||||
thiserror = { version = "1.0" }
|
||||
titlecase = { version = "2.2.1" }
|
||||
textwrap = { workspace = true }
|
||||
thiserror = { version = "1.0.38" }
|
||||
toml = { workspace = true }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
# For (future) wasm-pack support
|
||||
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
console_log = { version = "0.2.0" }
|
||||
serde-wasm-bindgen = { version = "0.4" }
|
||||
js-sys = { version = "0.3.60" }
|
||||
wasm-bindgen = { version = "0.2.83" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
is_executable = "1.0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.19.0", features = ["yaml", "redactions"] }
|
||||
test-case = { version = "2.2.2" }
|
||||
wasm-bindgen-test = { version = "0.3.33" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
|
||||
criterion = { version = "0.4.0" }
|
||||
insta = { workspace = true, features = ["yaml", "redactions"] }
|
||||
pretty_assertions = "1.3.0"
|
||||
test-case = { workspace = true }
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -107,3 +107,7 @@ class Foo:
|
||||
# ANN101
|
||||
def foo(self, /, a: int, b: int) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# OK
|
||||
def f(*args: *tuple[int]) -> None: ...
|
||||
|
||||
@@ -19,6 +19,8 @@ token = "s3cr3t"
|
||||
secrete = "s3cr3t"
|
||||
safe = password = "s3cr3t"
|
||||
password = safe = "s3cr3t"
|
||||
PASSWORD = "s3cr3t"
|
||||
PassWord = "s3cr3t"
|
||||
|
||||
d["password"] = "s3cr3t"
|
||||
d["pass"] = "s3cr3t"
|
||||
@@ -61,3 +63,15 @@ if token == "3\t4":
|
||||
|
||||
if token == "5\r6":
|
||||
pass
|
||||
|
||||
|
||||
# These should not be flagged
|
||||
passed_msg = "You have passed!"
|
||||
compassion = "Please don't match!"
|
||||
impassable = "You shall not pass!"
|
||||
passwords = ""
|
||||
PASSWORDS = ""
|
||||
passphrases = ""
|
||||
PassPhrases = ""
|
||||
tokens = ""
|
||||
secrets = ""
|
||||
|
||||
@@ -57,6 +57,12 @@ dict.fromkeys(("world",), True)
|
||||
{}.deploy(True, False)
|
||||
getattr(someobj, attrname, False)
|
||||
mylist.index(True)
|
||||
int(True)
|
||||
str(int(False))
|
||||
cfg.get("hello", True)
|
||||
cfg.getint("hello", True)
|
||||
cfg.getfloat("hello", True)
|
||||
cfg.getboolean("hello", True)
|
||||
|
||||
|
||||
class Registry:
|
||||
@@ -66,3 +72,11 @@ class Registry:
|
||||
# FBT001: Boolean positional arg in function definition
|
||||
def __setitem__(self, switch: Switch, value: bool) -> None:
|
||||
self._switches[switch.value] = value
|
||||
|
||||
@foo.setter
|
||||
def foo(self, value: bool) -> None:
|
||||
pass
|
||||
|
||||
# FBT001: Boolean positional arg in function definition
|
||||
def foo(self, value: bool) -> None:
|
||||
pass
|
||||
|
||||
@@ -105,3 +105,25 @@ while True:
|
||||
pass
|
||||
finally:
|
||||
break # warning
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
match *0, 1, *2:
|
||||
case 0,:
|
||||
y = 0
|
||||
case 0, *x:
|
||||
break # warning
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
match *0, 1, *2:
|
||||
case 0,:
|
||||
y = 0
|
||||
case 0, *x:
|
||||
pass # no warning
|
||||
|
||||
14
crates/ruff/resources/test/fixtures/flake8_bugbear/B029.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/flake8_bugbear/B029.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
Should emit:
|
||||
B029 - on lines 8 and 13
|
||||
"""
|
||||
|
||||
try:
|
||||
pass
|
||||
except ():
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except () as e:
|
||||
pass
|
||||
47
crates/ruff/resources/test/fixtures/flake8_bugbear/B030.py
vendored
Normal file
47
crates/ruff/resources/test/fixtures/flake8_bugbear/B030.py
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Should emit:
|
||||
B030:
|
||||
- line 12, column 8
|
||||
- line 17, column 9
|
||||
- line 22, column 21
|
||||
- line 27, column 37
|
||||
"""
|
||||
|
||||
try:
|
||||
pass
|
||||
except 1: # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (1, ValueError): # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, (RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *(RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *(RuntimeError, TypeError)): # ok
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *[RuntimeError, *(TypeError,)]): # ok
|
||||
pass
|
||||
|
||||
def what_to_catch():
|
||||
return ...
|
||||
|
||||
try:
|
||||
pass
|
||||
except what_to_catch(): # ok
|
||||
pass
|
||||
29
crates/ruff/resources/test/fixtures/flake8_bugbear/B032.py
vendored
Normal file
29
crates/ruff/resources/test/fixtures/flake8_bugbear/B032.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Should emit:
|
||||
B032 - on lines 9, 10, 12, 13, 16-19
|
||||
"""
|
||||
|
||||
# Flag these
|
||||
dct = {"a": 1}
|
||||
|
||||
dct["b"]: 2
|
||||
dct.b: 2
|
||||
|
||||
dct["b"]: "test"
|
||||
dct.b: "test"
|
||||
|
||||
test = "test"
|
||||
dct["b"]: test
|
||||
dct["b"]: test.lower()
|
||||
dct.b: test
|
||||
dct.b: test.lower()
|
||||
|
||||
# Do not flag below
|
||||
typed_dct: dict[str, int] = {"a": 1}
|
||||
typed_dct["b"] = 2
|
||||
typed_dct.b = 2
|
||||
|
||||
|
||||
class TestClass:
|
||||
def test_self(self):
|
||||
self.test: int
|
||||
@@ -62,3 +62,11 @@ except Exception as e:
|
||||
raise RuntimeError("boom!")
|
||||
else:
|
||||
raise RuntimeError("bang!")
|
||||
|
||||
|
||||
try:
|
||||
...
|
||||
except Exception as e:
|
||||
match 0:
|
||||
case 0:
|
||||
raise RuntimeError("boom!")
|
||||
|
||||
@@ -626,3 +626,8 @@ result = function(
|
||||
bar,
|
||||
**{'ham': spam}
|
||||
)
|
||||
|
||||
# Make sure the COM812 and UP034 rules don't autofix simultaneously and cause a syntax error.
|
||||
the_first_one = next(
|
||||
(i for i in range(10) if i // 2 == 0) # COM812 fix should include the final bracket
|
||||
)
|
||||
|
||||
21
crates/ruff/resources/test/fixtures/flake8_django/DJ003.py
vendored
Normal file
21
crates/ruff/resources/test/fixtures/flake8_django/DJ003.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def test_view1(request):
|
||||
return render(request, "index.html", locals())
|
||||
|
||||
|
||||
def test_view2(request):
|
||||
return render(request, "index.html", context=locals())
|
||||
|
||||
|
||||
def test_view3(request):
|
||||
return render(request, "index.html")
|
||||
|
||||
|
||||
def test_view4(request):
|
||||
return render(request, "index.html", {})
|
||||
|
||||
|
||||
def test_view5(request):
|
||||
return render(request, "index.html", context={})
|
||||
11
crates/ruff/resources/test/fixtures/flake8_django/DJ006.py
vendored
Normal file
11
crates/ruff/resources/test/fixtures/flake8_django/DJ006.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
from django import forms
|
||||
|
||||
|
||||
class TestModelForm1(forms.ModelForm):
|
||||
class Meta:
|
||||
exclude = ["bar"]
|
||||
|
||||
|
||||
class TestModelForm2(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = ["foo"]
|
||||
16
crates/ruff/resources/test/fixtures/flake8_django/DJ007.py
vendored
Normal file
16
crates/ruff/resources/test/fixtures/flake8_django/DJ007.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
from django import forms
|
||||
|
||||
|
||||
class TestModelForm1(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class TestModelForm2(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = b"__all__"
|
||||
|
||||
|
||||
class TestModelForm3(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = ["foo"]
|
||||
16
crates/ruff/resources/test/fixtures/flake8_pie/PIE802.py
vendored
Normal file
16
crates/ruff/resources/test/fixtures/flake8_pie/PIE802.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# no error
|
||||
all((x.id for x in bar))
|
||||
all(x.id for x in bar)
|
||||
all(x.id for x in bar)
|
||||
any(x.id for x in bar)
|
||||
any({x.id for x in bar})
|
||||
|
||||
# PIE 802
|
||||
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
|
||||
@@ -18,3 +18,10 @@ class Foo:
|
||||
|
||||
class FooTable(BaseTable):
|
||||
bar = fields.ListField(list)
|
||||
|
||||
|
||||
lambda *args, **kwargs: []
|
||||
|
||||
lambda *args: []
|
||||
|
||||
lambda **kwargs: []
|
||||
|
||||
@@ -6,6 +6,8 @@ obj.endswith("foo") or obj.endswith("bar")
|
||||
obj.startswith(foo) or obj.startswith(bar)
|
||||
# error
|
||||
obj.startswith(foo) or obj.startswith("foo")
|
||||
# error
|
||||
obj.endswith(foo) or obj.startswith(foo) or obj.startswith("foo")
|
||||
|
||||
# ok
|
||||
obj.startswith(("foo", "bar"))
|
||||
|
||||
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI006.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI006.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import sys
|
||||
from sys import version_info as python_version
|
||||
|
||||
if sys.version_info < (3, 9): ... # OK
|
||||
|
||||
if sys.version_info >= (3, 9): ... # OK
|
||||
|
||||
if sys.version_info == (3, 9): ... # OK
|
||||
|
||||
if sys.version_info <= (3, 10): ... # OK
|
||||
|
||||
if sys.version_info > (3, 10): ... # OK
|
||||
|
||||
if python_version > (3, 10): ... # OK
|
||||
18
crates/ruff/resources/test/fixtures/flake8_pyi/PYI006.pyi
vendored
Normal file
18
crates/ruff/resources/test/fixtures/flake8_pyi/PYI006.pyi
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import sys
|
||||
from sys import version_info as python_version
|
||||
|
||||
if sys.version_info < (3, 9): ... # OK
|
||||
|
||||
if sys.version_info >= (3, 9): ... # OK
|
||||
|
||||
if sys.version_info == (3, 9): ... # OK
|
||||
|
||||
if sys.version_info == (3, 9): ... # Error: PYI006 Use only `<` and `>=` for version info comparisons
|
||||
|
||||
if sys.version_info <= (3, 10): ... # Error: PYI006 Use only `<` and `>=` for version info comparisons
|
||||
|
||||
if sys.version_info <= (3, 10): ... # Error: PYI006 Use only `<` and `>=` for version info comparisons
|
||||
|
||||
if sys.version_info > (3, 10): ... # Error: PYI006 Use only `<` and `>=` for version info comparisons
|
||||
|
||||
if python_version > (3, 10): ... # Error: PYI006 Use only `<` and `>=` for version info comparisons
|
||||
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI009.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI009.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
def bar():
|
||||
... # OK
|
||||
|
||||
|
||||
def foo():
|
||||
pass # OK, since we're not in a stub file
|
||||
|
||||
|
||||
class Bar:
|
||||
... # OK
|
||||
|
||||
|
||||
class Foo:
|
||||
pass # OK, since we're not in a stub file
|
||||
8
crates/ruff/resources/test/fixtures/flake8_pyi/PYI009.pyi
vendored
Normal file
8
crates/ruff/resources/test/fixtures/flake8_pyi/PYI009.pyi
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
def bar(): ... # OK
|
||||
def foo():
|
||||
pass # ERROR PYI009, since we're in a stub file
|
||||
|
||||
class Bar: ... # OK
|
||||
|
||||
class Foo:
|
||||
pass # ERROR PYI009, since we're in a stub file
|
||||
18
crates/ruff/resources/test/fixtures/flake8_pyi/PYI010.py
vendored
Normal file
18
crates/ruff/resources/test/fixtures/flake8_pyi/PYI010.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
def bar():
|
||||
... # OK
|
||||
|
||||
|
||||
def foo():
|
||||
"""foo""" # OK
|
||||
|
||||
|
||||
def buzz():
|
||||
print("buzz") # OK, not in stub file
|
||||
|
||||
|
||||
def foo2():
|
||||
123 # OK, not in a stub file
|
||||
|
||||
|
||||
def bizz():
|
||||
x = 123 # OK, not in a stub file
|
||||
12
crates/ruff/resources/test/fixtures/flake8_pyi/PYI010.pyi
vendored
Normal file
12
crates/ruff/resources/test/fixtures/flake8_pyi/PYI010.pyi
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
def bar(): ... # OK
|
||||
def foo():
|
||||
"""foo""" # OK, strings are handled by another rule
|
||||
|
||||
def buzz():
|
||||
print("buzz") # ERROR PYI010
|
||||
|
||||
def foo2():
|
||||
123 # ERROR PYI010
|
||||
|
||||
def bizz():
|
||||
x = 123 # ERROR PYI010
|
||||
79
crates/ruff/resources/test/fixtures/flake8_pyi/PYI011.py
vendored
Normal file
79
crates/ruff/resources/test/fixtures/flake8_pyi/PYI011.py
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
def f12(
|
||||
x,
|
||||
y: str = os.pathsep, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f11(*, x: str = "x") -> None: # OK
|
||||
...
|
||||
|
||||
|
||||
def f13(
|
||||
x: list[str] = [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
] # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f14(
|
||||
x: tuple[str, ...] = (
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
) # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f15(
|
||||
x: set[str] = {
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
} # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f16(x: frozenset[bytes] = frozenset({b"foo", b"bar", b"baz"})) -> None: # OK
|
||||
...
|
||||
|
||||
|
||||
def f17(
|
||||
x: str = "foo" + "bar", # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f18(
|
||||
x: str = b"foo" + b"bar", # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f19(
|
||||
x: object = "foo" + 4, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f20(
|
||||
x: int = 5 + 5, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f21(
|
||||
x: complex = 3j - 3j, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f22(
|
||||
x: complex = -42.5j + 4.3j, # OK
|
||||
) -> None:
|
||||
...
|
||||
63
crates/ruff/resources/test/fixtures/flake8_pyi/PYI011.pyi
vendored
Normal file
63
crates/ruff/resources/test/fixtures/flake8_pyi/PYI011.pyi
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
def f12(
|
||||
x,
|
||||
y: str = os.pathsep, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f11(*, x: str = "x") -> None: ... # OK
|
||||
def f13(
|
||||
x: list[
|
||||
str
|
||||
] = [ # Error PYI011 Only simple default values allowed for typed arguments
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
]
|
||||
) -> None: ...
|
||||
def f14(
|
||||
x: tuple[
|
||||
str, ...
|
||||
] = ( # Error PYI011 Only simple default values allowed for typed arguments
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
)
|
||||
) -> None: ...
|
||||
def f15(
|
||||
x: set[
|
||||
str
|
||||
] = { # Error PYI011 Only simple default values allowed for typed arguments
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
}
|
||||
) -> None: ...
|
||||
def f16(
|
||||
x: frozenset[
|
||||
bytes
|
||||
] = frozenset( # Error PYI011 Only simple default values allowed for typed arguments
|
||||
{b"foo", b"bar", b"baz"}
|
||||
)
|
||||
) -> None: ...
|
||||
def f17(
|
||||
x: str = "foo" # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ "bar",
|
||||
) -> None: ...
|
||||
def f18(
|
||||
x: str = b"foo" # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ b"bar",
|
||||
) -> None: ...
|
||||
def f19(
|
||||
x: object = "foo" # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ 4,
|
||||
) -> None: ...
|
||||
def f20(
|
||||
x: int = 5
|
||||
+ 5, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f21(
|
||||
x: complex = 3j
|
||||
- 3j, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f22(
|
||||
x: complex = -42.5j # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ 4.3j,
|
||||
) -> None: ...
|
||||
79
crates/ruff/resources/test/fixtures/flake8_pyi/PYI014.py
vendored
Normal file
79
crates/ruff/resources/test/fixtures/flake8_pyi/PYI014.py
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
def f12(
|
||||
x,
|
||||
y=os.pathsep, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f11(*, x="x") -> None:
|
||||
... # OK
|
||||
|
||||
|
||||
def f13(
|
||||
x=[ # OK
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
]
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f14(
|
||||
x=( # OK
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
)
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f15(
|
||||
x={ # OK
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
}
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f16(x=frozenset({b"foo", b"bar", b"baz"})) -> None:
|
||||
... # OK
|
||||
|
||||
|
||||
def f17(
|
||||
x="foo" + "bar", # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f18(
|
||||
x=b"foo" + b"bar", # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f19(
|
||||
x="foo" + 4, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f20(
|
||||
x=5 + 5, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f21(
|
||||
x=3j - 3j, # OK
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f22(
|
||||
x=-42.5j + 4.3j, # OK
|
||||
) -> None:
|
||||
...
|
||||
48
crates/ruff/resources/test/fixtures/flake8_pyi/PYI014.pyi
vendored
Normal file
48
crates/ruff/resources/test/fixtures/flake8_pyi/PYI014.pyi
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
def f12(
|
||||
x,
|
||||
y=os.pathsep, # Error PYI014
|
||||
) -> None: ...
|
||||
def f11(*, x="x") -> None: ... # OK
|
||||
def f13(
|
||||
x=[ # Error PYI014
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
]
|
||||
) -> None: ...
|
||||
def f14(
|
||||
x=( # Error PYI014
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
)
|
||||
) -> None: ...
|
||||
def f15(
|
||||
x={ # Error PYI014
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
}
|
||||
) -> None: ...
|
||||
def f16(x=frozenset({b"foo", b"bar", b"baz"})) -> None: ... # Error PYI014
|
||||
def f17(
|
||||
x="foo" + "bar", # Error PYI014
|
||||
) -> None: ...
|
||||
def f18(
|
||||
x=b"foo" + b"bar", # Error PYI014
|
||||
) -> None: ...
|
||||
def f19(
|
||||
x="foo" + 4, # Error PYI014
|
||||
) -> None: ...
|
||||
def f20(
|
||||
x=5 + 5, # Error PYI014
|
||||
) -> None: ...
|
||||
def f21(
|
||||
x=3j - 3j, # Error PYI014
|
||||
) -> None: ...
|
||||
def f22(
|
||||
x=-42.5j + 4.3j, # Error PYI014
|
||||
) -> None: ...
|
||||
def f23(
|
||||
x=True, # OK
|
||||
) -> None: ...
|
||||
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI021.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/flake8_pyi/PYI021.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"""foo""" # OK, not in stub
|
||||
|
||||
|
||||
def foo():
|
||||
"""foo""" # OK, doc strings are allowed in non-stubs
|
||||
|
||||
|
||||
class Bar:
|
||||
"""bar""" # OK, doc strings are allowed in non-stubs
|
||||
|
||||
|
||||
def bar():
|
||||
x = 1
|
||||
"""foo""" # OK, not a doc string
|
||||
11
crates/ruff/resources/test/fixtures/flake8_pyi/PYI021.pyi
vendored
Normal file
11
crates/ruff/resources/test/fixtures/flake8_pyi/PYI021.pyi
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"""foo""" # ERROR PYI021
|
||||
|
||||
def foo():
|
||||
"""foo""" # ERROR PYI021
|
||||
|
||||
class Bar:
|
||||
"""bar""" # ERROR PYI021
|
||||
|
||||
def bar():
|
||||
x = 1
|
||||
"""foo""" # OK, not a doc string
|
||||
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.py
vendored
Normal file
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# From https://github.com/PyCQA/flake8-pyi/blob/4212bec43dbc4020a59b90e2957c9488575e57ba/tests/type_comments.pyi
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import TypeAlias
|
||||
|
||||
A: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
B: TypeAlias = None # type: str # And here's an extra comment about why it's that type # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
C: TypeAlias = None #type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
D: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
E: TypeAlias = None# type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
F: TypeAlias = None#type:int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
def func(
|
||||
arg1, # type: dict[str, int] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
arg2 # type: Sequence[bytes] # And here's some more info about this arg # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
): ...
|
||||
|
||||
class Foo:
|
||||
Attr: TypeAlias = None # type: set[str] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
G: TypeAlias = None # type: ignore
|
||||
H: TypeAlias = None # type: ignore[attr-defined]
|
||||
I: TypeAlias = None #type: ignore
|
||||
J: TypeAlias = None # type: ignore
|
||||
K: TypeAlias = None# type: ignore
|
||||
L: TypeAlias = None#type:ignore
|
||||
|
||||
# Whole line commented out # type: int
|
||||
M: TypeAlias = None # type: can't parse me!
|
||||
|
||||
class Bar:
|
||||
N: TypeAlias = None # type: can't parse me either!
|
||||
# This whole line is commented out and indented # type: str
|
||||
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.pyi
vendored
Normal file
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.pyi
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# From https://github.com/PyCQA/flake8-pyi/blob/4212bec43dbc4020a59b90e2957c9488575e57ba/tests/type_comments.pyi
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import TypeAlias
|
||||
|
||||
A: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
B: TypeAlias = None # type: str # And here's an extra comment about why it's that type # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
C: TypeAlias = None #type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
D: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
E: TypeAlias = None# type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
F: TypeAlias = None#type:int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
def func(
|
||||
arg1, # type: dict[str, int] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
arg2 # type: Sequence[bytes] # And here's some more info about this arg # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
): ...
|
||||
|
||||
class Foo:
|
||||
Attr: TypeAlias = None # type: set[str] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
G: TypeAlias = None # type: ignore
|
||||
H: TypeAlias = None # type: ignore[attr-defined]
|
||||
I: TypeAlias = None #type: ignore
|
||||
J: TypeAlias = None # type: ignore
|
||||
K: TypeAlias = None# type: ignore
|
||||
L: TypeAlias = None#type:ignore
|
||||
|
||||
# Whole line commented out # type: int
|
||||
M: TypeAlias = None # type: can't parse me!
|
||||
|
||||
class Bar:
|
||||
N: TypeAlias = None # type: can't parse me either!
|
||||
# This whole line is commented out and indented # type: str
|
||||
@@ -17,6 +17,12 @@ class Test(unittest.TestCase):
|
||||
self.assertTrue(**{"expr": expr, "msg": msg}) # Error, unfixable
|
||||
self.assertTrue(msg=msg, expr=expr, unexpected_arg=False) # Error, unfixable
|
||||
self.assertTrue(msg=msg) # Error, unfixable
|
||||
(
|
||||
self.assertIsNotNone(value) # Error, unfixable
|
||||
if expect_condition
|
||||
else self.assertIsNone(value) # Error, unfixable
|
||||
)
|
||||
return self.assertEqual(True, False) # Error, unfixable
|
||||
|
||||
def test_assert_false(self):
|
||||
self.assertFalse(True) # Error
|
||||
|
||||
@@ -9,6 +9,7 @@ def test_ok():
|
||||
assert something, "something message"
|
||||
assert something or something_else and something_third, "another message"
|
||||
|
||||
|
||||
def test_error():
|
||||
assert something and something_else
|
||||
assert something and something_else and something_third
|
||||
@@ -17,13 +18,24 @@ def test_error():
|
||||
assert not something and something_else
|
||||
assert not (something or something_else)
|
||||
assert not (something or something_else or something_third)
|
||||
assert something and something_else == """error
|
||||
message
|
||||
"""
|
||||
|
||||
# recursive case
|
||||
assert not (a or not (b or c))
|
||||
assert not (a or not (b and c)) # note that we only reduce once here
|
||||
assert not (a or not (b and c))
|
||||
|
||||
# detected, but no autofix for messages
|
||||
assert something and something_else, "error message"
|
||||
assert not (something or something_else and something_third), "with message"
|
||||
# detected, but no autofix for mixed conditions (e.g. `a or b and c`)
|
||||
assert not (something or something_else and something_third)
|
||||
# detected, but no autofix for parenthesized conditions
|
||||
assert (
|
||||
something
|
||||
and something_else
|
||||
== """error
|
||||
message
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -3,6 +3,8 @@ import os
|
||||
import posix
|
||||
from posix import abort
|
||||
import sys as std_sys
|
||||
import typing
|
||||
import typing_extensions
|
||||
import _thread
|
||||
import _winapi
|
||||
|
||||
@@ -77,7 +79,7 @@ def x(y):
|
||||
|
||||
# last line in while loop
|
||||
def x(y):
|
||||
while True:
|
||||
while i > 0:
|
||||
if y > 0:
|
||||
return 1
|
||||
y += 1
|
||||
@@ -211,6 +213,18 @@ def noreturn_sys_exit():
|
||||
std_sys.exit(0)
|
||||
|
||||
|
||||
def noreturn_typing_assert_never():
|
||||
if x > 0:
|
||||
return 1
|
||||
typing.assert_never(0)
|
||||
|
||||
|
||||
def noreturn_typing_extensions_assert_never():
|
||||
if x > 0:
|
||||
return 1
|
||||
typing_extensions.assert_never(0)
|
||||
|
||||
|
||||
def noreturn__thread_exit():
|
||||
if x > 0:
|
||||
return 1
|
||||
@@ -259,3 +273,50 @@ def nested(values):
|
||||
|
||||
for value in values:
|
||||
print(value)
|
||||
|
||||
|
||||
def while_true():
|
||||
while True:
|
||||
if y > 0:
|
||||
return 1
|
||||
y += 1
|
||||
|
||||
|
||||
# match
|
||||
def x(y):
|
||||
match y:
|
||||
case 0:
|
||||
return 1
|
||||
case 1:
|
||||
print() # error
|
||||
|
||||
|
||||
def foo(baz: str) -> str:
|
||||
return baz
|
||||
|
||||
|
||||
def end_of_statement():
|
||||
def example():
|
||||
if True:
|
||||
return ""
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return ""
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" # type: ignore
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" ;
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" \
|
||||
; # type: ignore
|
||||
|
||||
@@ -6,22 +6,6 @@ def x():
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print(a)
|
||||
a = 2
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
if True:
|
||||
return a # error
|
||||
a = 2
|
||||
print(a)
|
||||
return a
|
||||
|
||||
|
||||
# Can be refactored false positives
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issuecomment-1122571066
|
||||
def get_bar_if_exists(obj):
|
||||
@@ -165,44 +149,6 @@ def my_func():
|
||||
return foo
|
||||
|
||||
|
||||
# Refactored incorrect false positives
|
||||
# See test cases above marked: "Can be refactored false positives"
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issuecomment-1122571066
|
||||
def get_bar_if_exists(obj):
|
||||
if hasattr(obj, "bar"):
|
||||
return str(obj.bar)
|
||||
return ""
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issue-641117366
|
||||
def x():
|
||||
formatted = _USER_AGENT_FORMATTER.format(format_string, **values)
|
||||
# clean up after any blank components
|
||||
return formatted.replace("()", "").replace(" ", " ").strip()
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issue-641117366
|
||||
def user_agent_username(username=None):
|
||||
|
||||
if not username:
|
||||
return ""
|
||||
|
||||
username = username.replace(" ", "_") # Avoid spaces or %20.
|
||||
try:
|
||||
username.encode("ascii") # just test,
|
||||
# but not actually use it
|
||||
except UnicodeEncodeError:
|
||||
username = quote(username.encode("utf-8"))
|
||||
else:
|
||||
# % is legal in the default $wgLegalTitleChars
|
||||
# This is so that ops know the real pywikibot will not
|
||||
# allow a useragent in the username to allow through a
|
||||
# hand-coded percent-encoded value.
|
||||
if "%" in username:
|
||||
username = quote(username)
|
||||
return username
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/116#issue-1367575481
|
||||
def no_exception_loop():
|
||||
success = False
|
||||
@@ -260,3 +206,44 @@ def nonlocal_assignment():
|
||||
nonlocal X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
|
||||
def decorator() -> Flask:
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/hello')
|
||||
def hello() -> str:
|
||||
"""Hello endpoint."""
|
||||
return 'Hello, World!'
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def default():
|
||||
y = 1
|
||||
|
||||
def f(x = y) -> X:
|
||||
return x
|
||||
|
||||
return y
|
||||
|
||||
|
||||
def get_queryset(option_1, option_2):
|
||||
queryset: Any = None
|
||||
queryset = queryset.filter(a=1)
|
||||
if option_1:
|
||||
queryset = queryset.annotate(b=Value(2))
|
||||
if option_2:
|
||||
queryset = queryset.filter(c=3)
|
||||
return queryset
|
||||
|
||||
|
||||
def get_queryset():
|
||||
queryset = Model.filter(a=1)
|
||||
queryset = queryset.filter(c=3)
|
||||
return queryset
|
||||
|
||||
|
||||
def get_queryset():
|
||||
queryset = Model.filter(a=1)
|
||||
return queryset # error
|
||||
|
||||
86
crates/ruff/resources/test/fixtures/flake8_simplify/SIM116.py
vendored
Normal file
86
crates/ruff/resources/test/fixtures/flake8_simplify/SIM116.py
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
# Errors
|
||||
a = "hello"
|
||||
|
||||
# SIM116
|
||||
if a == "foo":
|
||||
return "bar"
|
||||
elif a == "bar":
|
||||
return "baz"
|
||||
elif a == "boo":
|
||||
return "ooh"
|
||||
else:
|
||||
return 42
|
||||
|
||||
# SIM116
|
||||
if a == 1:
|
||||
return (1, 2, 3)
|
||||
elif a == 2:
|
||||
return (4, 5, 6)
|
||||
elif a == 3:
|
||||
return (7, 8, 9)
|
||||
else:
|
||||
return (10, 11, 12)
|
||||
|
||||
# SIM116
|
||||
if a == 1:
|
||||
return (1, 2, 3)
|
||||
elif a == 2:
|
||||
return (4, 5, 6)
|
||||
elif a == 3:
|
||||
return (7, 8, 9)
|
||||
|
||||
# SIM116
|
||||
if a == "hello 'sir'":
|
||||
return (1, 2, 3)
|
||||
elif a == 'goodbye "mam"':
|
||||
return (4, 5, 6)
|
||||
elif a == """Fairwell 'mister'""":
|
||||
return (7, 8, 9)
|
||||
else:
|
||||
return (10, 11, 12)
|
||||
|
||||
# SIM116
|
||||
if a == b"one":
|
||||
return 1
|
||||
elif a == b"two":
|
||||
return 2
|
||||
elif a == b"three":
|
||||
return 3
|
||||
|
||||
# SIM116
|
||||
if a == "hello 'sir'":
|
||||
return ("hello'", 'hi"', 3)
|
||||
elif a == 'goodbye "mam"':
|
||||
return (4, 5, 6)
|
||||
elif a == """Fairwell 'mister'""":
|
||||
return (7, 8, 9)
|
||||
else:
|
||||
return (10, 11, 12)
|
||||
|
||||
# OK
|
||||
if a == "foo":
|
||||
return "bar"
|
||||
elif a == "bar":
|
||||
return baz()
|
||||
elif a == "boo":
|
||||
return "ooh"
|
||||
else:
|
||||
return 42
|
||||
|
||||
# OK
|
||||
if a == b"one":
|
||||
return 1
|
||||
elif b == b"two":
|
||||
return 2
|
||||
elif a == b"three":
|
||||
return 3
|
||||
|
||||
# SIM116
|
||||
if func_name == "create":
|
||||
return "A"
|
||||
elif func_name == "modify":
|
||||
return "M"
|
||||
elif func_name == "remove":
|
||||
return "D"
|
||||
elif func_name == "move":
|
||||
return "MV"
|
||||
@@ -6,11 +6,14 @@
|
||||
"yoda" <= compare # SIM300
|
||||
"yoda" < compare # SIM300
|
||||
42 > age # SIM300
|
||||
-42 > age # SIM300
|
||||
+42 > age # SIM300
|
||||
YODA == age # SIM300
|
||||
YODA > age # SIM300
|
||||
YODA >= age # SIM300
|
||||
JediOrder.YODA == age # SIM300
|
||||
0 < (number - 100) # SIM300
|
||||
SomeClass().settings.SOME_CONSTANT_VALUE > (60 * 60) # SIM300
|
||||
|
||||
# OK
|
||||
compare == "yoda"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from typing import TYPE_CHECKING, Any, ClassVar
|
||||
|
||||
|
||||
import attrs
|
||||
|
||||
from ....import unknown
|
||||
from ..protocol import commands, definitions, responses
|
||||
from ..server import example
|
||||
from .. import server
|
||||
|
||||
3
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_14.pyi
vendored
Normal file
3
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_14.pyi
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
from typing import Tuple
|
||||
|
||||
x: Tuple
|
||||
38
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_1.py
vendored
Normal file
38
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_1.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pydantic
|
||||
from pydantic import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime # TCH004
|
||||
from array import array # TCH004
|
||||
|
||||
import pandas # TCH004
|
||||
import pyproj
|
||||
|
||||
|
||||
class A(pydantic.BaseModel):
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
class B(BaseModel):
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
class C(BaseModel):
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
class E:
|
||||
pass
|
||||
|
||||
|
||||
class F(E):
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
class G(BaseModel):
|
||||
x: array
|
||||
28
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_2.py
vendored
Normal file
28
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_2.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import geopandas as gpd # TCH002
|
||||
import pydantic
|
||||
import pyproj # TCH002
|
||||
from pydantic import BaseModel
|
||||
|
||||
import numpy
|
||||
|
||||
|
||||
class A(BaseModel):
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
class B(pydantic.BaseModel):
|
||||
x: numpy.ndarray
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
class D(C):
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
class E(C):
|
||||
x: gpd.GeoDataFrame
|
||||
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_3.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_3.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import pathlib
|
||||
from uuid import UUID # TCH003
|
||||
|
||||
import pydantic
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class A(pydantic.BaseModel):
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
class B(BaseModel):
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
class D(C):
|
||||
x: UUID
|
||||
46
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_1.py
vendored
Normal file
46
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_1.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import attrs
|
||||
from attrs import frozen
|
||||
|
||||
import numpy
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime # TCH004
|
||||
from array import array # TCH004
|
||||
|
||||
import pandas # TCH004
|
||||
import pyproj
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
@attrs.define
|
||||
class B:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@frozen(auto_attribs=True)
|
||||
class C:
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
@frozen
|
||||
class D:
|
||||
x: array
|
||||
|
||||
|
||||
@dataclass
|
||||
class E:
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
@attrs.define
|
||||
class F:
|
||||
x: numpy.ndarray
|
||||
30
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_2.py
vendored
Normal file
30
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_2.py
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
import attrs
|
||||
import pandas
|
||||
import pyproj
|
||||
from attrs import frozen
|
||||
|
||||
import numpy # TCH002
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
@attrs.define
|
||||
class B:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@frozen
|
||||
class C:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@dataclass
|
||||
class D:
|
||||
x: numpy.ndarray
|
||||
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_3.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_3.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from array import array
|
||||
from dataclasses import dataclass
|
||||
from uuid import UUID # TCH003
|
||||
|
||||
import attrs
|
||||
from attrs import frozen
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
@frozen
|
||||
class B:
|
||||
x: array
|
||||
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
x: UUID
|
||||
15
crates/ruff/resources/test/fixtures/isort/as_imports_comments.py
vendored
Normal file
15
crates/ruff/resources/test/fixtures/isort/as_imports_comments.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
from foo import ( # Comment on `foo`
|
||||
Member as Alias, # Comment on `Alias`
|
||||
)
|
||||
|
||||
from bar import ( # Comment on `bar`
|
||||
Member, # Comment on `Member`
|
||||
)
|
||||
|
||||
from baz import ( # Comment on `baz`
|
||||
Member as Alias # Comment on `Alias`
|
||||
)
|
||||
|
||||
from bop import ( # Comment on `bop`
|
||||
Member # Comment on `Member`
|
||||
)
|
||||
@@ -1,2 +1,2 @@
|
||||
from long_module_name import member_one, member_two, member_three, member_four, member_five
|
||||
from long_module_name import member_one, member_two, member_three, member_four, member_five
|
||||
|
||||
|
||||
3
crates/ruff/resources/test/fixtures/isort/no_lines_before_with_empty_sections.py
vendored
Normal file
3
crates/ruff/resources/test/fixtures/isort/no_lines_before_with_empty_sections.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
from __future__ import annotations
|
||||
from typing import Any
|
||||
from . import my_local_folder_object
|
||||
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/0001_initial.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/0001_initial.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/__main__.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/__main__.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/__setup__.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/__setup__.py
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/file-with-dashes
vendored
Normal file
0
crates/ruff/resources/test/fixtures/pep8_naming/N999/module/valid_name/file-with-dashes
vendored
Normal file
14
crates/ruff/resources/test/fixtures/pycodestyle/E21.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/pycodestyle/E21.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#: E211
|
||||
spam (1)
|
||||
#: E211 E211
|
||||
dict ['key'] = list [index]
|
||||
#: E211
|
||||
dict['key'] ['subkey'] = list[index]
|
||||
#: Okay
|
||||
spam(1)
|
||||
dict['key'] = list[index]
|
||||
|
||||
|
||||
# This is not prohibited by PEP8, but avoid it.
|
||||
class Foo (Bar, Baz):
|
||||
pass
|
||||
15
crates/ruff/resources/test/fixtures/pycodestyle/E23.py
vendored
Normal file
15
crates/ruff/resources/test/fixtures/pycodestyle/E23.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#: E231
|
||||
a = (1,2)
|
||||
#: E231
|
||||
a[b1,:]
|
||||
#: E231
|
||||
a = [{'a':''}]
|
||||
#: Okay
|
||||
a = (4,)
|
||||
b = (5, )
|
||||
c = {'text': text[5:]}
|
||||
|
||||
result = {
|
||||
'key1': 'value',
|
||||
'key2': 'value',
|
||||
}
|
||||
50
crates/ruff/resources/test/fixtures/pycodestyle/E25.py
vendored
Normal file
50
crates/ruff/resources/test/fixtures/pycodestyle/E25.py
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
#: E251 E251
|
||||
def foo(bar = False):
|
||||
'''Test function with an error in declaration'''
|
||||
pass
|
||||
#: E251
|
||||
foo(bar= True)
|
||||
#: E251
|
||||
foo(bar =True)
|
||||
#: E251 E251
|
||||
foo(bar = True)
|
||||
#: E251
|
||||
y = bar(root= "sdasd")
|
||||
#: E251:2:29
|
||||
parser.add_argument('--long-option',
|
||||
default=
|
||||
"/rather/long/filesystem/path/here/blah/blah/blah")
|
||||
#: E251:1:45
|
||||
parser.add_argument('--long-option', default
|
||||
="/rather/long/filesystem/path/here/blah/blah/blah")
|
||||
#: E251:3:8 E251:3:10
|
||||
foo(True,
|
||||
baz=(1, 2),
|
||||
biz = 'foo'
|
||||
)
|
||||
#: Okay
|
||||
foo(bar=(1 == 1))
|
||||
foo(bar=(1 != 1))
|
||||
foo(bar=(1 >= 1))
|
||||
foo(bar=(1 <= 1))
|
||||
(options, args) = parser.parse_args()
|
||||
d[type(None)] = _deepcopy_atomic
|
||||
|
||||
# Annotated Function Definitions
|
||||
#: Okay
|
||||
def munge(input: AnyStr, sep: AnyStr = None, limit=1000,
|
||||
extra: Union[str, dict] = None) -> AnyStr:
|
||||
pass
|
||||
#: Okay
|
||||
async def add(a: int = 0, b: int = 0) -> int:
|
||||
return a + b
|
||||
# Previously E251 four times
|
||||
#: E271:1:6
|
||||
async def add(a: int = 0, b: int = 0) -> int:
|
||||
return a + b
|
||||
#: E252:1:15 E252:1:16 E252:1:27 E252:1:36
|
||||
def add(a: int=0, b: int =0, c: int= 0) -> int:
|
||||
return a + b + c
|
||||
#: Okay
|
||||
def add(a: int = _default(name='f')):
|
||||
return a
|
||||
@@ -54,3 +54,9 @@ def f(): ...
|
||||
class C: ...; x = 1
|
||||
#: E701:1:8 E702:1:13
|
||||
class C: ...; ...
|
||||
#: E701:2:12
|
||||
match *0, 1, *2:
|
||||
case 0,: y = 0
|
||||
#:
|
||||
class Foo:
|
||||
match: Optional[Match] = None
|
||||
|
||||
@@ -9,6 +9,9 @@ while False:
|
||||
f = lambda: (yield 1)
|
||||
#: E731
|
||||
f = lambda: (yield from g())
|
||||
#: E731
|
||||
class F:
|
||||
f = lambda x: 2 * x
|
||||
|
||||
f = object()
|
||||
f.method = lambda: "Method"
|
||||
|
||||
145
crates/ruff/resources/test/fixtures/pycodestyle/W19.py
vendored
Normal file
145
crates/ruff/resources/test/fixtures/pycodestyle/W19.py
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
#: W191
|
||||
if False:
|
||||
print # indented with 1 tab
|
||||
#:
|
||||
|
||||
|
||||
#: W191
|
||||
y = x == 2 \
|
||||
or x == 3
|
||||
#: E101 W191 W504
|
||||
if (
|
||||
x == (
|
||||
3
|
||||
) or
|
||||
y == 4):
|
||||
pass
|
||||
#: E101 W191
|
||||
if x == 2 \
|
||||
or y > 1 \
|
||||
or x == 3:
|
||||
pass
|
||||
#: E101 W191
|
||||
if x == 2 \
|
||||
or y > 1 \
|
||||
or x == 3:
|
||||
pass
|
||||
#:
|
||||
|
||||
#: E101 W191 W504
|
||||
if (foo == bar and
|
||||
baz == bop):
|
||||
pass
|
||||
#: E101 W191 W504
|
||||
if (
|
||||
foo == bar and
|
||||
baz == bop
|
||||
):
|
||||
pass
|
||||
#:
|
||||
|
||||
#: E101 E101 W191 W191
|
||||
if start[1] > end_col and not (
|
||||
over_indent == 4 and indent_next):
|
||||
return (0, "E121 continuation line over-"
|
||||
"indented for visual indent")
|
||||
#:
|
||||
|
||||
#: E101 W191
|
||||
|
||||
|
||||
def long_function_name(
|
||||
var_one, var_two, var_three,
|
||||
var_four):
|
||||
print(var_one)
|
||||
#: E101 W191 W504
|
||||
if ((row < 0 or self.moduleCount <= row or
|
||||
col < 0 or self.moduleCount <= col)):
|
||||
raise Exception("%s,%s - %s" % (row, col, self.moduleCount))
|
||||
#: E101 E101 E101 E101 W191 W191 W191 W191 W191 W191
|
||||
if bar:
|
||||
return (
|
||||
start, 'E121 lines starting with a '
|
||||
'closing bracket should be indented '
|
||||
"to match that of the opening "
|
||||
"bracket's line"
|
||||
)
|
||||
#
|
||||
#: E101 W191 W504
|
||||
# you want vertical alignment, so use a parens
|
||||
if ((foo.bar("baz") and
|
||||
foo.bar("bop")
|
||||
)):
|
||||
print "yes"
|
||||
#: E101 W191 W504
|
||||
# also ok, but starting to look like LISP
|
||||
if ((foo.bar("baz") and
|
||||
foo.bar("bop"))):
|
||||
print "yes"
|
||||
#: E101 W191 W504
|
||||
if (a == 2 or
|
||||
b == "abc def ghi"
|
||||
"jkl mno"):
|
||||
return True
|
||||
#: E101 W191 W504
|
||||
if (a == 2 or
|
||||
b == """abc def ghi
|
||||
jkl mno"""):
|
||||
return True
|
||||
#: W191:2:1 W191:3:1 E101:3:2
|
||||
if length > options.max_line_length:
|
||||
return options.max_line_length, \
|
||||
"E501 line too long (%d characters)" % length
|
||||
|
||||
|
||||
#
|
||||
#: E101 W191 W191 W504
|
||||
if os.path.exists(os.path.join(path, PEP8_BIN)):
|
||||
cmd = ([os.path.join(path, PEP8_BIN)] +
|
||||
self._pep8_options(targetfile))
|
||||
#: W191
|
||||
'''
|
||||
multiline string with tab in it'''
|
||||
#: E101 W191
|
||||
'''multiline string
|
||||
with tabs
|
||||
and spaces
|
||||
'''
|
||||
#: Okay
|
||||
'''sometimes, you just need to go nuts in a multiline string
|
||||
and allow all sorts of crap
|
||||
like mixed tabs and spaces
|
||||
|
||||
or trailing whitespace
|
||||
or long long long long long long long long long long long long long long long long long lines
|
||||
''' # nopep8
|
||||
#: Okay
|
||||
'''this one
|
||||
will get no warning
|
||||
even though the noqa comment is not immediately after the string
|
||||
''' + foo # noqa
|
||||
#
|
||||
#: E101 W191
|
||||
if foo is None and bar is "bop" and \
|
||||
blah == 'yeah':
|
||||
blah = 'yeahnah'
|
||||
|
||||
|
||||
#
|
||||
#: W191 W191 W191
|
||||
if True:
|
||||
foo(
|
||||
1,
|
||||
2)
|
||||
#: W191 W191 W191 W191 W191
|
||||
def test_keys(self):
|
||||
"""areas.json - All regions are accounted for."""
|
||||
expected = set([
|
||||
u'Norrbotten',
|
||||
u'V\xe4sterbotten',
|
||||
])
|
||||
#: W191
|
||||
x = [
|
||||
'abc'
|
||||
]
|
||||
#:
|
||||
26
crates/ruff/resources/test/fixtures/pycodestyle/W29.py
vendored
Normal file
26
crates/ruff/resources/test/fixtures/pycodestyle/W29.py
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#: Okay
|
||||
# 情
|
||||
#: W291:1:6
|
||||
print
|
||||
#: W293:2:1
|
||||
class Foo(object):
|
||||
|
||||
bang = 12
|
||||
#: W291:2:35
|
||||
'''multiline
|
||||
string with trailing whitespace'''
|
||||
#: W291 W292 noeol
|
||||
x = 1
|
||||
#: W191 W292 noeol
|
||||
if False:
|
||||
pass # indented with tabs
|
||||
#: W292:1:36 noeol
|
||||
# This line doesn't have a linefeed
|
||||
#: W292:1:5 E225:1:2 noeol
|
||||
1+ 1
|
||||
#: W292:1:27 E261:1:12 noeol
|
||||
import this # no line feed
|
||||
#: W292:3:22 noeol
|
||||
class Test(object):
|
||||
def __repr__(self):
|
||||
return 'test'
|
||||
@@ -1,35 +1,35 @@
|
||||
#: W605:1:10
|
||||
regex = '\.png$'
|
||||
|
||||
#: W605:2:1
|
||||
regex = '''
|
||||
\.png$
|
||||
'''
|
||||
|
||||
#: W605:2:6
|
||||
f(
|
||||
'\_'
|
||||
)
|
||||
|
||||
#: W605:4:6
|
||||
"""
|
||||
multi-line
|
||||
literal
|
||||
with \_ somewhere
|
||||
in the middle
|
||||
"""
|
||||
|
||||
#: Okay
|
||||
regex = r'\.png$'
|
||||
regex = '\\.png$'
|
||||
regex = r'''
|
||||
\.png$
|
||||
'''
|
||||
regex = r'''
|
||||
\\.png$
|
||||
'''
|
||||
s = '\\'
|
||||
regex = '\w' # noqa
|
||||
regex = '''
|
||||
\w
|
||||
''' # noqa
|
||||
#: W605:1:10
|
||||
regex = '\.png$'
|
||||
|
||||
#: W605:2:1
|
||||
regex = '''
|
||||
\.png$
|
||||
'''
|
||||
|
||||
#: W605:2:6
|
||||
f(
|
||||
'\_'
|
||||
)
|
||||
|
||||
#: W605:4:6
|
||||
"""
|
||||
multi-line
|
||||
literal
|
||||
with \_ somewhere
|
||||
in the middle
|
||||
"""
|
||||
|
||||
#: Okay
|
||||
regex = r'\.png$'
|
||||
regex = '\\.png$'
|
||||
regex = r'''
|
||||
\.png$
|
||||
'''
|
||||
regex = r'''
|
||||
\\.png$
|
||||
'''
|
||||
s = '\\'
|
||||
regex = '\w' # noqa
|
||||
regex = '''
|
||||
\w
|
||||
''' # noqa
|
||||
|
||||
@@ -16,21 +16,17 @@ if False == None: # E711, E712 (fix)
|
||||
if None == False: # E711, E712 (fix)
|
||||
pass
|
||||
|
||||
###
|
||||
# Unfixable errors
|
||||
###
|
||||
if "abc" == None: # E711
|
||||
pass
|
||||
if None == "abc": # E711
|
||||
pass
|
||||
if "abc" == False: # E712
|
||||
pass
|
||||
if False == "abc": # E712
|
||||
pass
|
||||
|
||||
###
|
||||
# Non-errors
|
||||
###
|
||||
if "abc" == None:
|
||||
pass
|
||||
if None == "abc":
|
||||
pass
|
||||
if "abc" == False:
|
||||
pass
|
||||
if False == "abc":
|
||||
pass
|
||||
if "def" == "abc":
|
||||
pass
|
||||
if False is None:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from functools import cached_property
|
||||
|
||||
from gi.repository import GObject
|
||||
|
||||
# Bad examples
|
||||
|
||||
def bad_liouiwnlkjl():
|
||||
@@ -76,6 +78,11 @@ class Thingy:
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
return self._beep
|
||||
|
||||
@GObject.Property
|
||||
def good_custom_property(self):
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
return self._beep
|
||||
|
||||
@cached_property
|
||||
def good_cached_property(self):
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
|
||||
1
crates/ruff/resources/test/fixtures/pydocstyle/bom.py
vendored
Normal file
1
crates/ruff/resources/test/fixtures/pydocstyle/bom.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
''' SAM macro definitions '''
|
||||
@@ -85,3 +85,10 @@ else:
|
||||
|
||||
|
||||
CustomInt: TypeAlias = "np.int8 | np.int16"
|
||||
|
||||
|
||||
# Test: match statements.
|
||||
match *0, 1, *2:
|
||||
case 0,:
|
||||
import x
|
||||
import y
|
||||
|
||||
10
crates/ruff/resources/test/fixtures/pyflakes/F401_10.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/pyflakes/F401_10.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
"""Test: imports within `ModuleNotFoundError` handlers."""
|
||||
|
||||
|
||||
def check_orjson():
|
||||
try:
|
||||
import orjson
|
||||
|
||||
return True
|
||||
except ModuleNotFoundError:
|
||||
return False
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Test that shadowing a global with a class attribute does not produce a
|
||||
warning.
|
||||
"""
|
||||
Test that shadowing a global with a class attribute does not produce a
|
||||
warning.
|
||||
"""
|
||||
|
||||
import fu
|
||||
|
||||
|
||||
4
crates/ruff/resources/test/fixtures/pyflakes/F821_10.py
vendored
Normal file
4
crates/ruff/resources/test/fixtures/pyflakes/F821_10.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
try:
|
||||
pass
|
||||
except ExceptionGroup:
|
||||
pass
|
||||
23
crates/ruff/resources/test/fixtures/pyflakes/F821_11.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/pyflakes/F821_11.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Test case: strings used within calls within type annotations."""
|
||||
|
||||
from typing import Callable
|
||||
|
||||
import bpy
|
||||
from mypy_extensions import VarArg
|
||||
|
||||
from foo import Bar
|
||||
|
||||
|
||||
class LightShow(bpy.types.Operator):
|
||||
label = "Create Character"
|
||||
name = "lightshow.letter_creation"
|
||||
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH") # OK
|
||||
|
||||
|
||||
def f(x: Callable[[VarArg("os")], None]): # F821
|
||||
pass
|
||||
|
||||
|
||||
f(Callable[["Bar"], None])
|
||||
f(Callable[["Baz"], None])
|
||||
25
crates/ruff/resources/test/fixtures/pyflakes/F821_12.py
vendored
Normal file
25
crates/ruff/resources/test/fixtures/pyflakes/F821_12.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"""Test case: strings used within calls within type annotations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable
|
||||
|
||||
import bpy
|
||||
from mypy_extensions import VarArg
|
||||
|
||||
from foo import Bar
|
||||
|
||||
|
||||
class LightShow(bpy.types.Operator):
|
||||
label = "Create Character"
|
||||
name = "lightshow.letter_creation"
|
||||
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH") # OK
|
||||
|
||||
|
||||
def f(x: Callable[[VarArg("os")], None]): # F821
|
||||
pass
|
||||
|
||||
|
||||
f(Callable[["Bar"], None])
|
||||
f(Callable[["Baz"], None])
|
||||
46
crates/ruff/resources/test/fixtures/pyflakes/F821_9.py
vendored
Normal file
46
crates/ruff/resources/test/fixtures/pyflakes/F821_9.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Test: match statements."""
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Car:
|
||||
make: str
|
||||
model: str
|
||||
|
||||
|
||||
def f():
|
||||
match Car("Toyota", "Corolla"):
|
||||
case Car("Toyota", model):
|
||||
print(model)
|
||||
case Car(make, "Corolla"):
|
||||
print(make)
|
||||
|
||||
|
||||
def f(provided: int) -> int:
|
||||
match provided:
|
||||
case True:
|
||||
return captured # F821
|
||||
|
||||
|
||||
def f(provided: int) -> int:
|
||||
match provided:
|
||||
case captured:
|
||||
return captured
|
||||
|
||||
|
||||
def f(provided: int) -> int:
|
||||
match provided:
|
||||
case [captured, *_]:
|
||||
return captured
|
||||
|
||||
|
||||
def f(provided: int) -> int:
|
||||
match provided:
|
||||
case [*captured]:
|
||||
return captured
|
||||
|
||||
|
||||
def f(provided: int) -> int:
|
||||
match provided:
|
||||
case {**captured}:
|
||||
return captured
|
||||
@@ -71,7 +71,7 @@ def f():
|
||||
def connect():
|
||||
return None, None
|
||||
|
||||
with (connect() as (connection, cursor)):
|
||||
with connect() as (connection, cursor):
|
||||
cursor.execute("SELECT * FROM users")
|
||||
|
||||
|
||||
@@ -94,3 +94,30 @@ def f():
|
||||
(exponential := (exponential * base_multiplier) % 3): i + 1 for i in range(2)
|
||||
}
|
||||
return hash_map
|
||||
|
||||
|
||||
def f(x: int):
|
||||
msg1 = "Hello, world!"
|
||||
msg2 = "Hello, world!"
|
||||
msg3 = "Hello, world!"
|
||||
match x:
|
||||
case 1:
|
||||
print(msg1)
|
||||
case 2:
|
||||
print(msg2)
|
||||
|
||||
|
||||
def f(x: int):
|
||||
import enum
|
||||
|
||||
Foo = enum.Enum("Foo", "A B")
|
||||
Bar = enum.Enum("Bar", "A B")
|
||||
Baz = enum.Enum("Baz", "A B")
|
||||
|
||||
match x:
|
||||
case (Foo.A):
|
||||
print("A")
|
||||
case [Bar.A, *_]:
|
||||
print("A")
|
||||
case y:
|
||||
pass
|
||||
|
||||
49
crates/ruff/resources/test/fixtures/pylint/collapsible_else_if.py
vendored
Normal file
49
crates/ruff/resources/test/fixtures/pylint/collapsible_else_if.py
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Test for else-if-used
|
||||
"""
|
||||
|
||||
|
||||
def ok0():
|
||||
"""Should not trigger on elif"""
|
||||
if 1:
|
||||
pass
|
||||
elif 2:
|
||||
pass
|
||||
|
||||
|
||||
def ok1():
|
||||
"""If the orelse has more than 1 item in it, shouldn't trigger"""
|
||||
if 1:
|
||||
pass
|
||||
else:
|
||||
print()
|
||||
if 1:
|
||||
pass
|
||||
|
||||
|
||||
def ok2():
|
||||
"""If the orelse has more than 1 item in it, shouldn't trigger"""
|
||||
if 1:
|
||||
pass
|
||||
else:
|
||||
if 1:
|
||||
pass
|
||||
print()
|
||||
|
||||
|
||||
def not_ok0():
|
||||
if 1:
|
||||
pass
|
||||
else:
|
||||
if 2:
|
||||
pass
|
||||
|
||||
|
||||
def not_ok1():
|
||||
if 1:
|
||||
pass
|
||||
else:
|
||||
if 2:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
19
crates/ruff/resources/test/fixtures/pylint/compare_to_empty_string.py
vendored
Normal file
19
crates/ruff/resources/test/fixtures/pylint/compare_to_empty_string.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
x = "a string"
|
||||
y = "another string"
|
||||
z = ""
|
||||
|
||||
|
||||
def errors():
|
||||
if x is "" or x == "":
|
||||
print("x is an empty string")
|
||||
|
||||
if y is not "" or y != "":
|
||||
print("y is not an empty string")
|
||||
|
||||
if "" != z:
|
||||
print("z is an empty string")
|
||||
|
||||
|
||||
def ok():
|
||||
if x and not y:
|
||||
print("x is not an empty string, but y is an empty string")
|
||||
75
crates/ruff/resources/test/fixtures/pylint/global_statement.py
vendored
Normal file
75
crates/ruff/resources/test/fixtures/pylint/global_statement.py
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
# Adapted from:
|
||||
# https://github.com/PyCQA/pylint/blob/b70d2abd7fabe9bfd735a30b593b9cd5eaa36194/tests/functional/g/globals.py
|
||||
|
||||
CONSTANT = 1
|
||||
|
||||
|
||||
def FUNC():
|
||||
pass
|
||||
|
||||
|
||||
class CLASS:
|
||||
pass
|
||||
|
||||
|
||||
def fix_constant(value):
|
||||
"""All this is ok, but try not to use `global` ;)"""
|
||||
global CONSTANT # [global-statement]
|
||||
print(CONSTANT)
|
||||
CONSTANT = value
|
||||
|
||||
|
||||
def global_with_import():
|
||||
"""Should only warn for global-statement when using `Import` node"""
|
||||
global sys # [global-statement]
|
||||
import sys
|
||||
|
||||
|
||||
def global_with_import_from():
|
||||
"""Should only warn for global-statement when using `ImportFrom` node"""
|
||||
global namedtuple # [global-statement]
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
def global_del():
|
||||
"""Deleting the global name prevents `global-variable-not-assigned`"""
|
||||
global CONSTANT # [global-statement]
|
||||
print(CONSTANT)
|
||||
del CONSTANT
|
||||
|
||||
|
||||
def global_operator_assign():
|
||||
"""Operator assigns should only throw a global statement error"""
|
||||
global CONSTANT # [global-statement]
|
||||
print(CONSTANT)
|
||||
CONSTANT += 1
|
||||
|
||||
|
||||
def global_function_assign():
|
||||
"""Function assigns should only throw a global statement error"""
|
||||
global CONSTANT # [global-statement]
|
||||
|
||||
def CONSTANT():
|
||||
pass
|
||||
|
||||
CONSTANT()
|
||||
|
||||
|
||||
def override_func():
|
||||
"""Overriding a function should only throw a global statement error"""
|
||||
global FUNC # [global-statement]
|
||||
|
||||
def FUNC():
|
||||
pass
|
||||
|
||||
FUNC()
|
||||
|
||||
|
||||
def override_class():
|
||||
"""Overriding a class should only throw a global statement error"""
|
||||
global CLASS # [global-statement]
|
||||
|
||||
class CLASS:
|
||||
pass
|
||||
|
||||
CLASS()
|
||||
8
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py
vendored
Normal file
8
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import os
|
||||
|
||||
tempVar = os.getenv("TEST", 12) # [invalid-envvar-default]
|
||||
goodVar = os.getenv("TESTING", None)
|
||||
dictVarBad = os.getenv("AAA", {"a", 7}) # [invalid-envvar-default]
|
||||
print(os.getenv("TEST", False)) # [invalid-envvar-default]
|
||||
os.getenv("AA", "GOOD")
|
||||
os.getenv("B", Z)
|
||||
12
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py
vendored
Normal file
12
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
|
||||
os.getenv(1) # [invalid-envvar-value]
|
||||
os.getenv("a")
|
||||
os.getenv("test")
|
||||
os.getenv(key="testingAgain")
|
||||
os.getenv(key=11) # [invalid-envvar-value]
|
||||
os.getenv(["hello"]) # [invalid-envvar-value]
|
||||
os.getenv(key="foo", default="bar")
|
||||
|
||||
AA = "aa"
|
||||
os.getenv(AA)
|
||||
24
crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import logging
|
||||
|
||||
logging.warning("Hello %s %s", "World!") # [logging-too-few-args]
|
||||
|
||||
# do not handle calls with kwargs (like pylint)
|
||||
logging.warning("Hello %s", "World!", "again", something="else")
|
||||
|
||||
logging.warning("Hello %s", "World!")
|
||||
|
||||
# do not handle calls without any args
|
||||
logging.info("100% dynamic")
|
||||
|
||||
# do not handle calls with *args
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", *args)
|
||||
|
||||
# do not handle calls with **kwargs
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
|
||||
|
||||
# do not handle keyword arguments
|
||||
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d")
|
||||
|
||||
import warning
|
||||
|
||||
warning.warning("Hello %s %s", "World!")
|
||||
20
crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py
vendored
Normal file
20
crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import logging
|
||||
|
||||
logging.warning("Hello %s", "World!", "again") # [logging-too-many-args]
|
||||
|
||||
logging.warning("Hello %s", "World!", "again", something="else")
|
||||
|
||||
logging.warning("Hello %s", "World!")
|
||||
|
||||
# do not handle calls with *args
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", *args)
|
||||
|
||||
# do not handle calls with **kwargs
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
|
||||
|
||||
# do not handle keyword arguments
|
||||
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d", {"objects": 1, "modifications": 1, "errors": 1})
|
||||
|
||||
import warning
|
||||
|
||||
warning.warning("Hello %s", "World!", "again")
|
||||
@@ -11,6 +11,9 @@ if 10 == 100: # [comparison-of-constants] R0133
|
||||
if 1 == 3: # [comparison-of-constants] R0133
|
||||
pass
|
||||
|
||||
if 1 == -3: # [comparison-of-constants] R0133
|
||||
pass
|
||||
|
||||
x = 0
|
||||
if 4 == 3 == x: # [comparison-of-constants] R0133
|
||||
pass
|
||||
@@ -35,6 +38,12 @@ if argc != 1: # correct
|
||||
if argc != 2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if argc != -2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if argc != +2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if __name__ == "__main__": # correct
|
||||
pass
|
||||
|
||||
|
||||
155
crates/ruff/resources/test/fixtures/pylint/redefined_loop_name.py
vendored
Normal file
155
crates/ruff/resources/test/fixtures/pylint/redefined_loop_name.py
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
# For -> for, variable reused
|
||||
for i in []:
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# With -> for, variable reused
|
||||
with None as i:
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> with, variable reused
|
||||
for i in []:
|
||||
with None as i: # error
|
||||
pass
|
||||
|
||||
# With -> with, variable reused
|
||||
with None as i:
|
||||
with None as i: # error
|
||||
pass
|
||||
|
||||
# For -> for, different variable
|
||||
for i in []:
|
||||
for j in []: # ok
|
||||
pass
|
||||
|
||||
# With -> with, different variable
|
||||
with None as i:
|
||||
with None as j: # ok
|
||||
pass
|
||||
|
||||
# For -> for -> for, doubly nested variable reuse
|
||||
for i in []:
|
||||
for j in []:
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> for -> for -> for, doubly nested variable reuse x2
|
||||
for i in []:
|
||||
for j in []:
|
||||
for i in []: # error
|
||||
for j in []: # error
|
||||
pass
|
||||
|
||||
# For -> assignment
|
||||
for i in []:
|
||||
i = 5 # error
|
||||
|
||||
# For -> augmented assignment
|
||||
for i in []:
|
||||
i += 5 # error
|
||||
|
||||
# For -> annotated assignment
|
||||
for i in []:
|
||||
i: int = 5 # error
|
||||
|
||||
# Async for -> for, variable reused
|
||||
async for i in []:
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> async for, variable reused
|
||||
for i in []:
|
||||
async for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> for, outer loop unpacks tuple
|
||||
for i, j in enumerate([]):
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> for, inner loop unpacks tuple
|
||||
for i in []:
|
||||
for i, j in enumerate([]): # error
|
||||
pass
|
||||
|
||||
# For -> for, both loops unpack tuple
|
||||
for (i, (j, k)) in []:
|
||||
for i, j in enumerate([]): # two errors
|
||||
pass
|
||||
|
||||
# For else -> for, variable reused in else
|
||||
for i in []:
|
||||
pass
|
||||
else:
|
||||
for i in []: # no error
|
||||
pass
|
||||
|
||||
# For -> for, ignore dummy variables
|
||||
for _ in []:
|
||||
for _ in []: # no error
|
||||
pass
|
||||
|
||||
# For -> for, outer loop unpacks with asterisk
|
||||
for i, *j in []:
|
||||
for j in []: # error
|
||||
pass
|
||||
|
||||
# For -> function definition
|
||||
for i in []:
|
||||
def f():
|
||||
i = 2 # no error
|
||||
|
||||
# For -> class definition
|
||||
for i in []:
|
||||
class A:
|
||||
i = 2 # no error
|
||||
|
||||
# For -> function definition -> for -> assignment
|
||||
for i in []:
|
||||
def f():
|
||||
for i in []: # no error
|
||||
i = 2 # error
|
||||
|
||||
# For -> class definition -> for -> for
|
||||
for i in []:
|
||||
class A:
|
||||
for i in []: # no error
|
||||
for i in []: # error
|
||||
pass
|
||||
|
||||
# For -> use in assignment target without actual assignment; subscript
|
||||
for i in []:
|
||||
a[i] = 2 # no error
|
||||
i[a] = 2 # no error
|
||||
|
||||
# For -> use in assignment target without actual assignment; attribute
|
||||
for i in []:
|
||||
a.i = 2 # no error
|
||||
i.a = 2 # no error
|
||||
|
||||
# For target with subscript -> assignment
|
||||
for a[0] in []:
|
||||
a[0] = 2 # error
|
||||
a[1] = 2 # no error
|
||||
|
||||
# For target with subscript -> assignment
|
||||
for a['i'] in []:
|
||||
a['i'] = 2 # error
|
||||
a['j'] = 2 # no error
|
||||
|
||||
# For target with attribute -> assignment
|
||||
for a.i in []:
|
||||
a.i = 2 # error
|
||||
a.j = 2 # no error
|
||||
|
||||
# For target with double nested attribute -> assignment
|
||||
for a.i.j in []:
|
||||
a.i.j = 2 # error
|
||||
a.j.i = 2 # no error
|
||||
|
||||
# For target with attribute -> assignment with different spacing
|
||||
for a.i in []:
|
||||
a. i = 2 # error
|
||||
for a. i in []:
|
||||
a.i = 2 # error
|
||||
@@ -124,3 +124,14 @@ def test_break_in_with():
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def test_break_in_match():
|
||||
"""no false positive for break in match"""
|
||||
for name in ["demo"]:
|
||||
match name:
|
||||
case "demo":
|
||||
break
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -25,22 +25,7 @@ avoid-escape = true
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.pep8-naming]
|
||||
ignore-names = [
|
||||
"setUp",
|
||||
"tearDown",
|
||||
"setUpClass",
|
||||
"tearDownClass",
|
||||
"setUpModule",
|
||||
"tearDownModule",
|
||||
"asyncSetUp",
|
||||
"asyncTearDown",
|
||||
"setUpTestData",
|
||||
"failureException",
|
||||
"longMessage",
|
||||
"maxDiff",
|
||||
]
|
||||
classmethod-decorators = ["classmethod", "pydantic.validator"]
|
||||
staticmethod-decorators = ["staticmethod"]
|
||||
classmethod-decorators = ["pydantic.validator"]
|
||||
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
ban-relative-imports = "parents"
|
||||
|
||||
@@ -28,3 +28,10 @@ def f(x: IList[str]) -> None:
|
||||
|
||||
def f(x: "List[str]") -> None:
|
||||
...
|
||||
|
||||
|
||||
list = "abc"
|
||||
|
||||
|
||||
def f(x: List[str]) -> None:
|
||||
...
|
||||
|
||||
@@ -41,3 +41,8 @@ def f(x: Union["str", int]) -> None:
|
||||
|
||||
def f(x: Union[("str", "int"), float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f() -> None:
|
||||
x: Optional[str]
|
||||
x = Optional[str]
|
||||
|
||||
@@ -12,11 +12,17 @@ Ipsum
|
||||
""".encode(
|
||||
"utf-8"
|
||||
)
|
||||
# b"""
|
||||
# Lorem
|
||||
#
|
||||
# Ipsum
|
||||
# """
|
||||
(
|
||||
"Lorem "
|
||||
"Ipsum".encode()
|
||||
)
|
||||
(
|
||||
"Lorem " # Comment
|
||||
"Ipsum".encode() # Comment
|
||||
)
|
||||
(
|
||||
"Lorem " "Ipsum".encode()
|
||||
)
|
||||
|
||||
# `encode` on variables should not be processed.
|
||||
string = "hello there"
|
||||
|
||||
@@ -2,36 +2,42 @@ from typing import TypedDict, NotRequired, Literal
|
||||
import typing
|
||||
|
||||
# dict literal
|
||||
MyType1 = TypedDict("MyType1", {"a": int, "b": str})
|
||||
MyType = TypedDict("MyType", {"a": int, "b": str})
|
||||
|
||||
# dict call
|
||||
MyType2 = TypedDict("MyType2", dict(a=int, b=str))
|
||||
MyType = TypedDict("MyType", dict(a=int, b=str))
|
||||
|
||||
# kwargs
|
||||
MyType3 = TypedDict("MyType3", a=int, b=str)
|
||||
MyType = TypedDict("MyType", a=int, b=str)
|
||||
|
||||
# Empty TypedDict
|
||||
MyType4 = TypedDict("MyType4")
|
||||
MyType = TypedDict("MyType")
|
||||
|
||||
# Literal values
|
||||
MyType5 = TypedDict("MyType5", {"a": "hello"})
|
||||
MyType6 = TypedDict("MyType6", a="hello")
|
||||
MyType = TypedDict("MyType", {"a": "hello"})
|
||||
MyType = TypedDict("MyType", a="hello")
|
||||
|
||||
# NotRequired
|
||||
MyType7 = TypedDict("MyType7", {"a": NotRequired[dict]})
|
||||
MyType = TypedDict("MyType", {"a": NotRequired[dict]})
|
||||
|
||||
# total
|
||||
MyType8 = TypedDict("MyType8", {"x": int, "y": int}, total=False)
|
||||
|
||||
# invalid identifiers
|
||||
MyType9 = TypedDict("MyType9", {"in": int, "x-y": int})
|
||||
MyType = TypedDict("MyType", {"x": int, "y": int}, total=False)
|
||||
|
||||
# using Literal type
|
||||
MyType10 = TypedDict("MyType10", {"key": Literal["value"]})
|
||||
MyType = TypedDict("MyType", {"key": Literal["value"]})
|
||||
|
||||
# using namespace TypedDict
|
||||
MyType11 = typing.TypedDict("MyType11", {"key": int})
|
||||
MyType = typing.TypedDict("MyType", {"key": int})
|
||||
|
||||
# unpacking
|
||||
# invalid identifiers (OK)
|
||||
MyType = TypedDict("MyType", {"in": int, "x-y": int})
|
||||
|
||||
# unpacking (OK)
|
||||
c = {"c": float}
|
||||
MyType12 = TypedDict("MyType1", {"a": int, "b": str, **c})
|
||||
MyType = TypedDict("MyType", {"a": int, "b": str, **c})
|
||||
|
||||
# Empty dict literal
|
||||
MyType = TypedDict("MyType", {})
|
||||
|
||||
# Empty dict call
|
||||
MyType = TypedDict("MyType", dict())
|
||||
|
||||
@@ -2,21 +2,30 @@ from typing import NamedTuple
|
||||
import typing
|
||||
|
||||
# with complex annotations
|
||||
NT1 = NamedTuple("NT1", [("a", int), ("b", tuple[str, ...])])
|
||||
MyType = NamedTuple("MyType", [("a", int), ("b", tuple[str, ...])])
|
||||
|
||||
# with default values as list
|
||||
NT2 = NamedTuple(
|
||||
"NT2",
|
||||
MyType = NamedTuple(
|
||||
"MyType",
|
||||
[("a", int), ("b", str), ("c", list[bool])],
|
||||
defaults=["foo", [True]],
|
||||
)
|
||||
|
||||
# with namespace
|
||||
NT3 = typing.NamedTuple("NT3", [("a", int), ("b", str)])
|
||||
MyType = typing.NamedTuple("MyType", [("a", int), ("b", str)])
|
||||
|
||||
# with too many default values
|
||||
NT4 = NamedTuple(
|
||||
"NT4",
|
||||
# too many default values (OK)
|
||||
MyType = NamedTuple(
|
||||
"MyType",
|
||||
[("a", int), ("b", str)],
|
||||
defaults=[1, "bar", "baz"],
|
||||
)
|
||||
|
||||
# invalid identifiers (OK)
|
||||
MyType = NamedTuple("MyType", [("x-y", int), ("b", tuple[str, ...])])
|
||||
|
||||
# no fields
|
||||
MyType = typing.NamedTuple("MyType")
|
||||
|
||||
# empty fields
|
||||
MyType = typing.NamedTuple("MyType", [])
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user