Compare commits

...

133 Commits

Author SHA1 Message Date
Charlie Marsh
125615af12 Bump version to 0.0.244 2023-02-08 17:28:59 -05:00
Charlie Marsh
6339f8e009 Use separate exit codes for fatal errors vs. lint errors (#2670) 2023-02-08 15:21:15 -05:00
Charlie Marsh
81abc5d7d8 Move error and warning messages into log macro (#2669) 2023-02-08 14:39:09 -05:00
Charlie Marsh
75fad989f4 Add --exit-non-zero-on-fix (#2668) 2023-02-08 14:27:54 -05:00
Charlie Marsh
cb4a221905 Treat annotated assignments in class and module scopes as runtime (#2667) 2023-02-08 13:59:25 -05:00
Charlie Marsh
286d8c18dd Remove ExprKind::Call from call path collection (#2666) 2023-02-08 13:35:18 -05:00
Florian Best
124461bddf test(UP003): let type reference be the builtin (#2664) 2023-02-08 12:44:37 -05:00
Charlie Marsh
7482a4a5b8 Avoid false-positive in chained type calls (#2663) 2023-02-08 12:18:36 -05:00
Charlie Marsh
9f9f25ff7c Accommodate multiple @pytest.mark.parametrize decorators (#2662) 2023-02-08 11:13:24 -05:00
Nuno Mendes
9cd1bf9c03 doc: add documentation for TRY002 (#2655) 2023-02-08 11:04:31 -05:00
Florian Best
3862dc2626 docs: use new command line arguments (#2658) 2023-02-08 10:36:53 -05:00
Charlie Marsh
2a0927a5ef Update Discord link 2023-02-08 04:36:59 -05:00
Charlie Marsh
824c0d2680 Implement whitespace-before-comment (E261, E262, E265, E266) (#2654) 2023-02-07 23:41:32 -05:00
Charlie Marsh
f5efdd058e Implement whitespace-around-keywords (E271, E272, E273, E274) (#2653) 2023-02-07 22:31:13 -05:00
Charlie Marsh
4c35feaa18 Add documentation for eradicate, flake8-import-conventions, and flake8-no-pep420 (#2652) 2023-02-07 22:19:21 -05:00
Charlie Marsh
8261d0656e Disable autofix for flake8-print rules (#2651) 2023-02-07 21:38:57 -05:00
Charlie Marsh
a9aa96b24f Add documentation for flake8-quotes rules (#2650) 2023-02-07 21:20:24 -05:00
Charlie Marsh
367f115d83 Add color to fixable error asterisk (#2647) 2023-02-07 19:12:18 -05:00
Charlie Marsh
56398e0002 Tweak format for rule explanations (#2645) 2023-02-07 19:02:41 -05:00
Ville Skyttä
4b49fd9494 Ignore all non-.py wrt. implicit namespace package (#2640)
It's not only `.pyi` that should be exempt for this, but also for example scripts which don't have an extension, explicitly passed in command line args.
2023-02-07 18:21:59 -05:00
Charlie Marsh
271e4fda8c Create per-rule pages and link from README (#2644) 2023-02-07 18:15:05 -05:00
Charlie Marsh
f1cdd108e6 Derive explanation method on Rule struct via rustdoc (#2642)
```console
❯ cargo run rule B017
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/ruff rule B017`
no-assert-raises-exception

Code: B017 (flake8-bugbear)

### What it does
Checks for `self.assertRaises(Exception)`.

## Why is this bad?
`assertRaises(Exception)` can lead to your test passing even if the
code being tested is never executed due to a typo.

Either assert for a more specific exception (builtin or custom), use
`assertRaisesRegex` or the context manager form of `assertRaises`.
```
2023-02-07 17:23:29 -05:00
Charlie Marsh
8fd29b3b60 Remove dependency on "unparse" feature (#2641) 2023-02-07 17:23:09 -05:00
Charlie Marsh
e427171323 Unify imports from rustpython_parser::ast (#2639) 2023-02-07 16:54:50 -05:00
Charlie Marsh
be08384fb0 Run cargo dev generate-all 2023-02-07 16:48:06 -05:00
Charlie Marsh
2f7f4943e3 Rename some local variables 2023-02-07 16:24:53 -05:00
Charlie Marsh
67e9ff7cc8 Reorder imports (#2638) 2023-02-07 16:22:47 -05:00
Charlie Marsh
0355ba571e Skip ternary fixes for yields and awaits (#2637) 2023-02-07 15:18:52 -05:00
Charlie Marsh
38db7fd114 Avoid boolean-trap errors in __setitem__ (#2636) 2023-02-07 15:04:33 -05:00
Charlie Marsh
8ee51eb5c6 Treat @staticmethod as higher-precedence than ABC (#2635) 2023-02-07 14:57:03 -05:00
Aarni Koskela
2bc16eb4e3 flake8-annotations: add ignore-fully-untyped (#2128)
This PR adds a configuration option to inhibit ANN* violations for functions that have no other annotations either, for easier gradual typing of a large codebase.
2023-02-07 11:35:57 -05:00
Charlie Marsh
4e36225145 Avoid no-unnecessary-dict-kwargs errors with reserved keywords (#2628) 2023-02-07 11:25:09 -05:00
Charlie Marsh
850069d0aa Avoid non-recursion in nested typing function calls (#2627) 2023-02-07 11:21:49 -05:00
Charlie Marsh
9fa98ed90b Accommodate pos-only arguments when checking self name (#2626) 2023-02-07 10:50:50 -05:00
Charlie Marsh
2b4ce78830 Delete unreferenced snapshots (#2619) 2023-02-06 23:22:41 -05:00
Colin Delahunty
7647cafe12 [pylint]: bidirectional-unicode (#2589) 2023-02-06 22:49:18 -05:00
Charlie Marsh
7686179318 Remove unused src/registry.rs 2023-02-06 22:43:25 -05:00
Charlie Marsh
bf718fdf26 Bump Ruff version to 0.0.243 2023-02-06 21:22:54 -05:00
Steve Dignam
3b3466f6da Add flake8-pie single_starts_ends_with (#2616) 2023-02-06 21:22:32 -05:00
Charlie Marsh
f981f491aa Support ignore-names for all relevant pep8-naming rules (#2617) 2023-02-06 21:14:55 -05:00
Charlie Marsh
95fef43c4d Add some additional tests for relative imports 2023-02-06 21:13:23 -05:00
Charlie Marsh
097c679cf3 Support relative paths for typing-modules (#2615) 2023-02-06 19:51:37 -05:00
Charlie Marsh
3bca987665 Avoid removing quotes from runtime annotations (#2614) 2023-02-06 18:15:19 -05:00
Ville Skyttä
60ee1d2c17 fix(pep8-naming): typing.NamedTuple and typing.TypedDict treatment (#2611) 2023-02-06 17:11:37 -05:00
Charlie Marsh
2dd04dd6a3 Check in updated snapshot 2023-02-06 16:34:47 -05:00
Charlie Marsh
e59b75d31b Bump version to 0.0.242 2023-02-06 16:25:29 -05:00
Charlie Marsh
610f150dd1 Remove autofix from bad-str-strip-call; add suggestions instead (#2610) 2023-02-06 16:25:20 -05:00
Charlie Marsh
cee0d0abaa Check in updated snapshot 2023-02-06 15:48:23 -05:00
Charlie Marsh
12ed1837ee Ignore typos in snapshots (#2609) 2023-02-06 15:43:03 -05:00
Colin Delahunty
6272293180 [pylint]: bad-str-strip-call (With Autofix) (#2570) 2023-02-06 15:34:37 -05:00
Charlie Marsh
f8b8b05b80 Visit deferred assignments after deferred type annotations (#2607) 2023-02-06 14:40:41 -05:00
Charlie Marsh
79776c12e2 Allow blank line before sticky-comment functions in docstrings (#2597) 2023-02-05 18:48:29 -05:00
Charlie Marsh
7fa5ce8b63 Automatically remove empty type-checking blocks (#2598) 2023-02-05 18:46:07 -05:00
Charlie Marsh
f6864a96f6 Enable autofix for unnecessary-paren-on-raise-exception (#2596) 2023-02-05 18:19:27 -05:00
Charlie Marsh
291ef9856a Remove unnecessary super_args.rs (#2594) 2023-02-05 18:02:09 -05:00
Charlie Marsh
87d0aa5561 Move python into its own ruff_python crate (#2593) 2023-02-05 17:53:58 -05:00
Charlie Marsh
ecc9f5de99 Fix accidental setup.py changes 2023-02-05 17:18:11 -05:00
Charlie Marsh
f40b974206 Add a description of project structure (#2590) 2023-02-05 17:01:09 -05:00
Micha Reiser
cd8be8c0be refactor: Introduce crates folder (#2088)
This PR introduces a new `crates` directory and moves all "product" crates into that folder. 

Part of #2059.
2023-02-05 16:47:48 -05:00
Charlie Marsh
e3dfa2e04e Implement pycodestyle's logical line detection (#1130)
Along with the logical line detection, this adds 14 of the missing `pycodestyle` rules.

For now, this is all gated behind a `logical_lines` feature that's off-by-default, which will let us implement all rules prior to shipping, since we want to couple the release of these rules with new defaults and instructions.
2023-02-05 15:06:02 -05:00
Ville Skyttä
f03c8fff14 fix(commented-out-code): mypy and SPDX-License-Identifier false positives (#2587)
https://mypy.readthedocs.io/en/stable/inline_config.html#configuration-comment-format
https://spdx.github.io/spdx-spec/v2.3/using-SPDX-short-identifiers-in-source-files/#e2-format-for-spdx-license-identifier
2023-02-05 15:04:36 -05:00
Charlie Marsh
452b5a4b79 Propagate attribute-like macros in define_rule_mapping (#2583)
This enables us to feature-flag rules, like:

```rust
ruff_macros::define_rule_mapping!(
    #[cfg(feature = "logical_lines")]
    E111 => rules::pycodestyle::rules::IndentationWithInvalidMultiple,
    ...
)
```
2023-02-05 12:26:23 -05:00
Colin Delahunty
1e1dc3a7ed [pyupgrade]: Removes quotes from annotations (#2431) 2023-02-05 09:43:09 -05:00
Charlie Marsh
84be1df9d5 Avoid infinite renames for unused-loop-control-variable (#2581) 2023-02-05 08:01:07 -05:00
Florian Best
6b3ae1a8e1 fix: fix syntax error in Python test COM81 (#2575) 2023-02-05 07:11:46 -05:00
Colin Delahunty
5275f6c90e Allows UP030 to work better with *args and **kwargs (#2568) 2023-02-04 17:34:48 -05:00
Anders Kaseorg
6683ed49bc Portably find ruff binary path from Python (#2574)
Prefer the version from a currently active virtualenv over a version
from `pip install --user`.  Add the .exe extension on Windows, and
find the path for `pip install --user` correctly on Windows.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-02-04 17:19:27 -05:00
Chris Chan
ced55084db Implement pylint's too-many-return-statements rule (PLR0911) (#2564) 2023-02-04 16:56:36 -05:00
Chris Chan
f8f36a7ee0 Implement pylint's too-many-branches rule (PLR0912) (#2550) 2023-02-04 16:38:03 -05:00
Charlie Marsh
4190031618 Run cargo fmt 2023-02-04 08:36:57 -05:00
Matteo Vitali
5a9258327b Fix python module invocation (#2563) 2023-02-04 08:23:13 -05:00
Charlie Marsh
dd0145624b Ignore direct root-children in implicit-namespace-package (#2565) 2023-02-04 08:21:24 -05:00
Charlie Marsh
7d4f0a8320 Bump Ruff version to 0.0.241 2023-02-03 19:25:12 -05:00
Charlie Marsh
4149bc7be8 Ignore direct source-children in implicit-namespace-package (#2560) 2023-02-03 19:20:27 -05:00
Pierre Sassoulas
e6316b185e [pylint] Rename 'too-many-args' to 'too-many-arguments'
The actual name
2023-02-03 18:58:32 -05:00
Pierre Sassoulas
a2183be96e [pylint] Rename constant-comparison to comparison-of-constant
The actual name
2023-02-03 18:58:32 -05:00
Pierre Sassoulas
df39a95925 [pylint] Rename use-sys-exit to consider-using-sys-exit
The actual name
2023-02-03 18:58:32 -05:00
Charlie Marsh
ff859ead85 Remove unused misplaced_comparison_constant.rs file 2023-02-03 17:10:48 -05:00
Charlie Marsh
b2be30cb07 Mark fixable issues in printer output (#2500) 2023-02-03 16:26:06 -05:00
Charlie Marsh
b9c1a3c5c1 Move benchmarking instructions to CONTRIBUTING.md (#2554) 2023-02-03 14:53:53 -05:00
Charlie Marsh
9751951d10 Allow F811 noqa declarations on containing import lines (#2553) 2023-02-03 14:51:06 -05:00
Charlie Marsh
64c79bde83 Mark sometimes-fixable rules as Availability::Sometimes (#2552) 2023-02-03 14:42:10 -05:00
Charlie Marsh
da0374f360 Update RustPython to pull in lexer optimizations (#2551) 2023-02-03 14:31:53 -05:00
Charlie Marsh
c26b58ba28 Hide globset logging even with --verbose 2023-02-03 13:31:04 -05:00
Charlie Marsh
56f935640a Avoid hang when detecting trailing comments (#2549) 2023-02-03 13:05:55 -05:00
Charlie Marsh
85ca6cde49 Fix a few nursery rule violations (#2548) 2023-02-03 11:59:29 -05:00
Aarni Koskela
38addbe50d Soft-deprecate update_check (#2530) 2023-02-03 11:33:38 -05:00
Charlie Marsh
924e35b1c3 Add print_stdout and print_stderr to Clippy enforcement (#2542) 2023-02-03 11:13:44 -05:00
Charlie Marsh
d05ea4dbac Exit upon showing files with --show-files (#2543) 2023-02-03 09:41:09 -05:00
Charlie Marsh
b5ac93d2ee Move Clippy configuration to config.toml (#2541) 2023-02-03 09:26:36 -05:00
Aarni Koskela
924e264156 Move flake8-{errmsg,print} violations (#2536) 2023-02-03 09:03:49 -05:00
Aarni Koskela
14c5000ad5 Move McCabe violations (#2534) 2023-02-03 08:41:11 -05:00
Aarni Koskela
d985473f4f Move pygrep-hooks violations (#2539) 2023-02-03 08:41:05 -05:00
Aarni Koskela
47e0b2521a Move flake8-2020 violations (#2537) 2023-02-03 08:40:56 -05:00
Aarni Koskela
a319980a7c Move pep8-naming violations (#2538) 2023-02-03 08:40:48 -05:00
Aarni Koskela
3336dd63f4 Move flake8-implicit-str-concat violations (#2535) 2023-02-03 08:24:06 -05:00
Aarni Koskela
ae20a721a1 Don't walk past project root when figuring out exclusion (#2471) 2023-02-03 08:23:51 -05:00
Aarni Koskela
a26b1f43e9 Move flake8-unused-arguments violations (#2533) 2023-02-03 08:19:18 -05:00
Chris Chan
139a6d8331 Minor fixes to PLR0915 logic (#2518) 2023-02-03 08:10:59 -05:00
Jacob Coffee
04ef674195 Add Jetbrains Webinar Event (Temporary) (#2516) 2023-02-03 08:08:27 -05:00
Aarni Koskela
db852a0b11 Move ruff violations (#2526) 2023-02-03 07:43:39 -05:00
Aarni Koskela
87c3b0e4e2 Move pydocstyle violations (#2524) 2023-02-03 07:42:52 -05:00
Aarni Koskela
82784a7607 Move flake8-debugger violation (#2522) 2023-02-03 07:40:53 -05:00
Aarni Koskela
f2da855048 Move flake8-datetimez violations (#2528) 2023-02-03 07:40:00 -05:00
Aarni Koskela
81b60cf9fe Move flake8-bandit violations (#2525) 2023-02-03 07:39:49 -05:00
Maksudul Haque
c96ba6dec4 [flake8-self] Fix False Negative Issue on Rule SLF001 (#2527) 2023-02-03 07:39:24 -05:00
Martin Fischer
0f8f250bea refactor: Simplify UpstreamCategory
There's no need to hardcode the prefix string since
it can be derived from the RuleCodePrefix.
2023-02-02 23:46:32 -05:00
Martin Fischer
a3ffaa5d9b refactor: Rename LinterCategory to UpstreamCategory
LinterCategory was somewhat misnamed since it's not actually
a category for linters but rather a category for upstream lints.
Since we want to introduce our own categories, naming the type
UpstreamCategory is more clear.
2023-02-02 23:46:32 -05:00
Martin Fischer
187ed874e9 refactor: Make Rule::from_code return Rule instead of &'static Rule 2023-02-02 23:46:32 -05:00
Charlie Marsh
a30c77e752 Mark --add-noqa as incompatible with --fix (#2513) 2023-02-02 23:43:05 -05:00
Florian Best
7e9b9cc7b3 feat: add autofix for PLR0402 (#2504) 2023-02-02 23:25:16 -05:00
Charlie Marsh
d4cef9305a Track overridden bindings within each scope (#2511) 2023-02-02 22:31:46 -05:00
Charlie Marsh
a074625121 Avoid renaming unused loop variables with deferred usages (#2509) 2023-02-02 20:59:47 -05:00
Charlie Marsh
9c55ab35df Change LogLevel comments to docs 2023-02-02 20:23:10 -05:00
Charlie Marsh
a95474f2b1 Use a copy-on-write to avoid extra contents clone (#2508) 2023-02-02 20:19:16 -05:00
Víctor
3e6fe46bc4 Add number of files processed in debug info (-v) (#2506) 2023-02-02 20:19:00 -05:00
Charlie Marsh
bc81cea4f4 Notify user if autofix introduces syntax error (#2507) 2023-02-02 20:02:09 -05:00
Charlie Marsh
cb0f226962 Always report parse errors back to the user (#2505) 2023-02-02 19:12:17 -05:00
Charlie Marsh
fa56fabed9 Remove a result wrapper from linter.rs (#2503) 2023-02-02 18:47:45 -05:00
Jonathan Plasse
bdcab87d2f Add markdownlint and dev Ruff to pre-commit (#2303) 2023-02-02 16:29:07 -05:00
Jonathan Plasse
ec8b827d26 Add known-standard-library for each Python version (#2491) 2023-02-02 16:22:47 -05:00
Jonathan Plasse
b232c43824 Fix an error in scripts/add_rule.py (#2497) 2023-02-02 15:58:11 -05:00
Charlie Marsh
ee01e666c5 Allow list() and tuple() calls in __all__ assignments (#2499) 2023-02-02 15:45:14 -05:00
Jonathan Plasse
2b0de8ccd9 Fix clippy error (#2498) 2023-02-02 15:38:18 -05:00
Aarni Koskela
739c57b31b Move flake8-annotations violations to rules file (#2496) 2023-02-02 15:17:54 -05:00
Aarni Koskela
c3e0137f22 Move flake8-return violations to rules module (#2492) 2023-02-02 15:13:49 -05:00
Aarni Koskela
77716108af Move flake8-simplify violations to rule modules (#2495) 2023-02-02 15:13:16 -05:00
Jonathan Plasse
335395adec Mirror CI clippy command for pre-commit hook (#2494) 2023-02-02 14:59:19 -05:00
Aarni Koskela
65f8f1a6f7 Move pylint violations to rule modules (#2489) 2023-02-02 14:47:58 -05:00
Aarni Koskela
858af8debb Move pyupgrade violations to rule modules (#2490) 2023-02-02 14:47:43 -05:00
Aarni Koskela
5f1bbf0b6b Move pycodestyle violations to rule modules (#2483) 2023-02-02 14:29:23 -05:00
Aarni Koskela
40cb905ae5 Move pyflakes violations to rule modules (#2488) 2023-02-02 14:00:59 -05:00
Jonathan Plasse
e89b4a5de5 Fix hardcoded url in transform_readme.py (#2487) 2023-02-02 13:59:22 -05:00
1894 changed files with 18885 additions and 10472 deletions

View File

@@ -1,2 +1,28 @@
[alias]
dev = "run --package ruff_dev --bin ruff_dev"
[target.'cfg(all())']
rustflags = [
# CLIPPY LINT SETTINGS
# This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML.
# See: `https://github.com/rust-lang/cargo/issues/5034`
# `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395`
"-Dunsafe_code",
"-Wclippy::pedantic",
# Allowed pedantic lints
"-Wclippy::char_lit_as_u8",
"-Aclippy::collapsible_else_if",
"-Aclippy::collapsible_if",
"-Aclippy::implicit_hasher",
"-Aclippy::match_same_arms",
"-Aclippy::missing_errors_doc",
"-Aclippy::missing_panics_doc",
"-Aclippy::module_name_repetitions",
"-Aclippy::must_use_candidate",
"-Aclippy::similar_names",
"-Aclippy::too_many_lines",
# Disallowed restriction lints
"-Wclippy::print_stdout",
"-Wclippy::print_stderr",
"-Wclippy::dbg_macro",
]

View File

@@ -3,8 +3,8 @@ Thank you for taking the time to report an issue! We're glad to have you involve
If you're filing a bug report, please consider including the following information:
- A minimal code snippet that reproduces the bug.
- The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
- The current Ruff settings (any relevant sections from your `pyproject.toml`).
- The current Ruff version (`ruff --version`).
* A minimal code snippet that reproduces the bug.
* The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
* The current Ruff settings (any relevant sections from your `pyproject.toml`).
* The current Ruff version (`ruff --version`).
-->

View File

@@ -50,13 +50,13 @@ jobs:
rustup component add clippy
rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v1
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
cargo-test:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: "cargo test | ${{ matrix.os }}"
steps:
@@ -69,13 +69,13 @@ jobs:
- name: "Run tests (Ubuntu)"
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
cargo insta test --all --delete-unreferenced-snapshots
cargo insta test --all --all-features --delete-unreferenced-snapshots
git diff --exit-code
- name: "Run tests (Windows)"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
run: |
cargo insta test --all
cargo insta test --all --all-features
git diff --exit-code
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
# Check for broken links in the documentation.
@@ -95,8 +95,8 @@ jobs:
- run: ./scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
- run: cargo check
- run: |
./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
- run: cargo check
maturin-build:
@@ -118,7 +118,7 @@ jobs:
name: "spell check"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: crate-ci/typos@master
with:
files: .
- uses: actions/checkout@v3
- uses: crate-ci/typos@master
with:
files: .

View File

@@ -6,10 +6,9 @@ on:
- README.md
- mkdocs.template.yml
- .github/workflows/docs.yaml
branches: [ main ]
branches: [main]
workflow_dispatch:
jobs:
mkdocs:
runs-on: ubuntu-latest

View File

@@ -15,7 +15,7 @@ jobs:
publish:
runs-on: ubuntu-latest
env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
@@ -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 . -- -p ruff
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff
- name: "Install Node dependencies"
run: npm ci
working-directory: playground

View File

@@ -138,7 +138,7 @@ jobs:
with:
target: ${{ matrix.target }}
manylinux: auto
args: --no-default-features --release --out dist
args: --release --out dist
- uses: uraimo/run-on-arch-action@v2.5.0
if: matrix.target != 'ppc64'
name: Install built wheel

5
.gitignore vendored
View File

@@ -1,7 +1,8 @@
# Local cache
.ruff_cache
resources/test/cpython
docs/
crates/ruff/resources/test/cpython
docs/*
!docs/rules
mkdocs.yml
.overrides

View File

@@ -1,16 +1,19 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.240
hooks:
- id: ruff
args: [--fix]
exclude: ^resources
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.10.1
hooks:
- id: validate-pyproject
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.33.0
hooks:
- id: markdownlint-fix
args:
- --disable
- MD013 # line-length
- MD033 # no-inline-html
- --
- repo: local
hooks:
- id: cargo-fmt
@@ -20,12 +23,22 @@ repos:
types: [rust]
- id: clippy
name: clippy
entry: cargo clippy --workspace --all-targets --all-features
entry: cargo clippy --workspace --all-targets --all-features -- -D warnings
language: rust
pass_filenames: false
- id: ruff
name: ruff
entry: cargo run -- --no-cache --fix
language: rust
types_or: [python, pyi]
require_serial: true
exclude: ^crates/ruff/resources
- id: dev-generate-all
name: dev-generate-all
entry: cargo dev generate-all
language: rust
pass_filenames: false
exclude: target
ci:
skip: [cargo-fmt, clippy, dev-generate-all]

View File

@@ -43,16 +43,18 @@ upgrades.
`--explain`, `--clean`, and `--generate-shell-completion` are now implemented as subcommands:
ruff . # Still works! And will always work.
ruff check . # New! Also works.
```console
ruff . # Still works! And will always work.
ruff check . # New! Also works.
ruff --explain E402 # Still works.
ruff rule E402 # New! Also works. (And preferred.)
ruff --explain E402 # Still works.
ruff rule E402 # New! Also works. (And preferred.)
# Oops! The command has to come first.
ruff --format json --explain E402 # No longer works.
ruff --explain E402 --format json # Still works!
ruff rule E402 --format json # Works! (And preferred.)
# Oops! The command has to come first.
ruff --format json --explain E402 # No longer works.
ruff --explain E402 --format json # Still works!
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:
@@ -60,7 +62,9 @@ no change in behavior. However, please note the following exceptions:
* Subcommands will now fail when invoked with unsupported arguments, instead
of silently ignoring them. For example, the following will now fail:
ruff --clean --respect-gitignore
```console
ruff --clean --respect-gitignore
```
(the `clean` command doesn't support `--respect-gitignore`.)

View File

@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
@@ -115,14 +115,12 @@ the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
version 2.0, available [here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
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 at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
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).

View File

@@ -10,7 +10,7 @@ For small changes (e.g., bug fixes), feel free to submit a PR.
For larger changes (e.g., new lint rules, new functionality, new configuration options), consider
creating an [**issue**](https://github.com/charliermarsh/ruff/issues) outlining your proposed
change. You can also join us on [**Discord**](https://discord.gg/Z8KbeK24) to discuss your idea with
change. You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5) to discuss your idea with
the community.
If you're looking for a place to start, we recommend implementing a new lint rule (see:
@@ -20,8 +20,7 @@ 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)
for guidance. [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998) has a few rules
left too.
for guidance.
### Prerequisites
@@ -39,16 +38,16 @@ cargo install cargo-insta
After cloning the repository, run Ruff locally with:
```shell
cargo run resources/test/fixtures --no-cache
cargo run 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 --all # Auto-formatting...
cargo clippy --fix --workspace --all-targets --all-features # Linting...
cargo test --all # Testing...
cargo test --all # Testing...
```
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
@@ -71,42 +70,60 @@ pre-commit run --all-files
Your Pull Request will be reviewed by a maintainer, which may involve a few rounds of iteration
prior to merging.
### Project structure
Ruff is structured as a monorepo with a [flat crate structure](https://matklad.github.io/2021/08/22/large-rust-workspaces.html),
such that all crates are contained in a flat `crates` directory.
The vast majority of the code, including all lint rules, lives in the `ruff` crate (located at
`crates/ruff`). As a contributor, that's the crate that'll be most relevant to you.
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.
### Example: Adding a new lint rule
At a high level, the steps involved in adding a new lint rule are as follows:
1. Create a file for your rule (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
2. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
3. Map the violation struct to a rule code in `src/registry.rs` (e.g., `E402`).
4. Define the logic for triggering the violation in `src/checkers/ast.rs` (for AST-based checks),
`src/checkers/tokens.rs` (for token-based checks), `src/checkers/lines.rs` (for text-based
checks), or `src/checkers/filesystem.rs` (for filesystem-based checks).
3. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
4. 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).
5. Add a test fixture.
6. 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., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
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
based on any required inputs. (Many of the existing examples live in `src/violations.rs`, but we're
looking to place new rules in their own files.)
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.)
To trigger the violation, you'll likely want to augment the logic in `src/checkers/ast.rs`, which
defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`,
which defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
collecting diagnostics as it goes.
If you need to inspect the AST, you can run `cargo dev print-ast` with a Python file. Grep
for the `Check::new` invocations to understand how other, similar rules are implemented.
To add a test fixture, create a file under `resources/test/fixtures/[linter]`, named to match
the code you defined earlier (e.g., `resources/test/fixtures/pycodestyle/E402.py`). This file should
To add a test fixture, create a file under `crates/ruff/resources/test/fixtures/[linter]`, named to match
the code you defined earlier (e.g., `crates/ruff/resources/test/fixtures/pycodestyle/E402.py`). This file should
contain a variety of violations and non-violations designed to evaluate and demonstrate the behavior
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 resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
locally with (e.g.) `cargo run 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 `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 --all`.
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.
@@ -116,13 +133,13 @@ Finally, regenerate the documentation and generated code with `cargo dev generat
Ruff's user-facing settings live in a few different places.
First, the command-line options are defined via the `Cli` struct in `src/cli.rs`.
First, the command-line options are defined via the `Cli` struct in `crates/ruff/src/cli.rs`.
Second, the `pyproject.toml` options are defined in `src/settings/options.rs` (via the `Options`
struct), `src/settings/configuration.rs` (via the `Configuration` struct), and `src/settings/mod.rs`
(via the `Settings` struct). These represent, respectively: the schema used to parse the
`pyproject.toml` file; an internal, intermediate representation; and the final, internal
representation used to power Ruff.
Second, the `pyproject.toml` options are defined in `crates/ruff/src/settings/options.rs` (via the
`Options` struct), `crates/ruff/src/settings/configuration.rs` (via the `Configuration` struct), and
`crates/ruff/src/settings/mod.rs` (via the `Settings` struct). These represent, respectively: the
schema used to parse the `pyproject.toml` file; an internal, intermediate representation; and the
final, internal representation used to power Ruff.
To add a new configuration option, you'll likely want to modify these latter few files (along with
`cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
@@ -130,11 +147,11 @@ To add a new configuration option, you'll likely want to modify these latter few
variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g.,
`src/flake8_unused_arguments/settings.rs`).
`crates/ruff/src/flake8_unused_arguments/settings.rs`).
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
lives in `flake8_to_ruff/src/converter.rs`.
lives in `crates/ruff/src/flake8_to_ruff/converter.rs`.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
@@ -146,3 +163,126 @@ them to [PyPI](https://pypi.org/project/ruff/).
Ruff follows the [semver](https://semver.org/) versioning standard. However, as pre-1.0 software,
even patch releases may contain [non-backwards-compatible changes](https://semver.org/#spec-item-4).
## Benchmarks
First, clone [CPython](https://github.com/python/cpython). It's a large and diverse Python codebase,
which makes it a good target for benchmarking.
```shell
git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff/resources/test/cpython
```
To benchmark the release build:
```shell
cargo build --release && hyperfine --ignore-failure --warmup 10 \
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
"./target/release/ruff ./crates/ruff/resources/test/cpython/"
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
Time (mean ± σ): 293.8 ms ± 3.2 ms [User: 2384.6 ms, System: 90.3 ms]
Range (min … max): 289.9 ms … 301.6 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: ./target/release/ruff ./crates/ruff/resources/test/cpython/
Time (mean ± σ): 48.0 ms ± 3.1 ms [User: 65.2 ms, System: 124.7 ms]
Range (min … max): 45.0 ms … 66.7 ms 62 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./crates/ruff/resources/test/cpython/' ran
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache'
```
To benchmark against the ecosystem's existing tools:
```shell
hyperfine --ignore-failure --warmup 5 \
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
"pyflakes crates/ruff/resources/test/cpython" \
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
"pycodestyle crates/ruff/resources/test/cpython" \
"flake8 crates/ruff/resources/test/cpython"
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
Time (mean ± σ): 294.3 ms ± 3.3 ms [User: 2467.5 ms, System: 89.6 ms]
Range (min … max): 291.1 ms … 302.8 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: pyflakes crates/ruff/resources/test/cpython
Time (mean ± σ): 15.786 s ± 0.143 s [User: 15.560 s, System: 0.214 s]
Range (min … max): 15.640 s … 16.157 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s]
Range (min … max): 5.950 s … 6.391 s 10 runs
Benchmark 4: pycodestyle crates/ruff/resources/test/cpython
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s]
Range (min … max): 46.171 s … 47.863 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 5: flake8 crates/ruff/resources/test/cpython
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s]
Range (min … max): 11.848 s … 12.933 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache' ran
20.98 ± 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
41.66 ± 1.18 times faster than 'flake8 crates/ruff/resources/test/cpython'
53.64 ± 0.77 times faster than 'pyflakes crates/ruff/resources/test/cpython'
159.43 ± 2.48 times faster than 'pycodestyle crates/ruff/resources/test/cpython'
```
You can run `poetry install` from `./scripts` to create a working environment for the above. All
reported benchmarks were computed using the versions specified by `./scripts/pyproject.toml`
on Python 3.11.
To benchmark Pylint, remove the following files from the CPython repository:
```shell
rm Lib/test/bad_coding.py \
Lib/test/bad_coding2.py \
Lib/test/bad_getattr.py \
Lib/test/bad_getattr2.py \
Lib/test/bad_getattr3.py \
Lib/test/badcert.pem \
Lib/test/badkey.pem \
Lib/test/badsyntax_3131.py \
Lib/test/badsyntax_future10.py \
Lib/test/badsyntax_future3.py \
Lib/test/badsyntax_future4.py \
Lib/test/badsyntax_future5.py \
Lib/test/badsyntax_future6.py \
Lib/test/badsyntax_future7.py \
Lib/test/badsyntax_future8.py \
Lib/test/badsyntax_future9.py \
Lib/test/badsyntax_pep3120.py \
Lib/test/test_asyncio/test_runners.py \
Lib/test/test_copy.py \
Lib/test/test_inspect.py \
Lib/test/test_typing.py
```
Then, from `crates/ruff/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
will execute Pylint with maximum parallelism and only report errors.
To benchmark Pyupgrade, run the following from `crates/ruff/resources/test/cpython`:
```shell
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \
"find . -type f -name \"*.py\" | xargs -P 0 pyupgrade --py311-plus"
Benchmark 1: find . -type f -name "*.py" | xargs -P 0 pyupgrade --py311-plus
Time (mean ± σ): 30.119 s ± 0.195 s [User: 28.638 s, System: 0.390 s]
Range (min … max): 29.813 s … 30.356 s 10 runs
```

277
Cargo.lock generated
View File

@@ -61,9 +61,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.68"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
[[package]]
name = "ascii"
@@ -86,7 +86,7 @@ version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e"
dependencies = [
"bstr 1.1.0",
"bstr 1.2.0",
"doc-comment",
"predicates",
"predicates-core",
@@ -126,6 +126,12 @@ dependencies = [
"serde",
]
[[package]]
name = "bisection"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "021e079a1bab0ecce6cf4b4b74c0c37afa4a697136eb3b127875c84a8f04a8c3"
[[package]]
name = "bit-set"
version = "0.5.3"
@@ -169,9 +175,9 @@ dependencies = [
[[package]]
name = "bstr"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832"
dependencies = [
"memchr",
"once_cell",
@@ -202,9 +208,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@@ -400,7 +406,7 @@ dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"windows-sys",
"windows-sys 0.42.0",
]
[[package]]
@@ -544,9 +550,9 @@ dependencies = [
[[package]]
name = "cxx"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b61a7545f753a88bcbe0a70de1fcc0221e10bfc752f576754fa91e663db1622e"
checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9"
dependencies = [
"cc",
"cxxbridge-flags",
@@ -556,9 +562,9 @@ dependencies = [
[[package]]
name = "cxx-build"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f464457d494b5ed6905c63b0c4704842aba319084a0a3561cdc1359536b53200"
checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d"
dependencies = [
"cc",
"codespan-reporting",
@@ -571,15 +577,15 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43c7119ce3a3701ed81aca8410b9acf6fc399d2629d057b87e2efa4e63a3aaea"
checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a"
[[package]]
name = "cxxbridge-macro"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e07508b90551e610910fa648a1878991d367064997a596135b86df30daf07e"
checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2"
dependencies = [
"proc-macro2",
"quote",
@@ -608,15 +614,6 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "directories"
version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs"
version = "4.0.0"
@@ -672,9 +669,9 @@ checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60"
[[package]]
name = "either"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "ena"
@@ -739,7 +736,7 @@ dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys",
"windows-sys 0.42.0",
]
[[package]]
@@ -750,7 +747,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.240"
version = "0.0.244"
dependencies = [
"anyhow",
"clap 4.1.4",
@@ -837,7 +834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
dependencies = [
"aho-corasick",
"bstr 1.1.0",
"bstr 1.2.0",
"fnv",
"log",
"regex",
@@ -860,9 +857,9 @@ dependencies = [
[[package]]
name = "heck"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
@@ -882,6 +879,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
[[package]]
name = "hexf-parse"
version = "0.2.1"
@@ -945,7 +948,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f92123bf2fe0d9f1b5df1964727b970ca3b2d0203d47cf97fb1f36d856b6398"
dependencies = [
"phf 0.11.1",
"phf",
"rust-stemmers",
]
@@ -1006,24 +1009,24 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
dependencies = [
"hermit-abi 0.2.6",
"hermit-abi 0.3.0",
"io-lifetimes",
"rustix",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@@ -1058,9 +1061,9 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
[[package]]
name = "js-sys"
version = "0.3.60"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
dependencies = [
"wasm-bindgen",
]
@@ -1271,7 +1274,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.42.0",
]
[[package]]
@@ -1331,9 +1334,9 @@ dependencies = [
[[package]]
name = "notify"
version = "5.0.0"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9"
dependencies = [
"bitflags",
"crossbeam-channel",
@@ -1344,7 +1347,7 @@ dependencies = [
"libc",
"mio",
"walkdir",
"winapi",
"windows-sys 0.42.0",
]
[[package]]
@@ -1449,15 +1452,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.6"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@@ -1571,15 +1574,6 @@ dependencies = [
"indexmap",
]
[[package]]
name = "phf"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
"phf_shared 0.10.0",
]
[[package]]
name = "phf"
version = "0.11.1"
@@ -1589,36 +1583,16 @@ dependencies = [
"phf_shared 0.11.1",
]
[[package]]
name = "phf_codegen"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
dependencies = [
"phf_generator 0.10.0",
"phf_shared 0.10.0",
]
[[package]]
name = "phf_codegen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator 0.11.1",
"phf_generator",
"phf_shared 0.11.1",
]
[[package]]
name = "phf_generator"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
dependencies = [
"phf_shared 0.10.0",
"rand",
]
[[package]]
name = "phf_generator"
version = "0.11.1"
@@ -1756,9 +1730,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.50"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
@@ -1922,9 +1896,10 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.240"
version = "0.0.244"
dependencies = [
"anyhow",
"bisection",
"bitflags",
"cfg-if",
"chrono",
@@ -1954,8 +1929,8 @@ dependencies = [
"path-absolutize",
"regex",
"ruff_macros",
"ruff_python",
"rustc-hash",
"rustpython-ast",
"rustpython-common",
"rustpython-parser",
"schemars",
@@ -1977,7 +1952,7 @@ dependencies = [
[[package]]
name = "ruff_cli"
version = "0.0.240"
version = "0.0.244"
dependencies = [
"annotate-snippets 0.9.1",
"anyhow",
@@ -2007,14 +1982,13 @@ dependencies = [
"similar",
"strum",
"textwrap",
"update-informer",
"ureq",
"walkdir",
]
[[package]]
name = "ruff_dev"
version = "0.0.240"
version = "0.0.244"
dependencies = [
"anyhow",
"clap 4.1.4",
@@ -2023,7 +1997,6 @@ dependencies = [
"once_cell",
"ruff",
"ruff_cli",
"rustpython-ast",
"rustpython-common",
"rustpython-parser",
"schemars",
@@ -2035,8 +2008,9 @@ dependencies = [
[[package]]
name = "ruff_macros"
version = "0.0.240"
version = "0.0.244"
dependencies = [
"itertools",
"once_cell",
"proc-macro2",
"quote",
@@ -2044,6 +2018,15 @@ dependencies = [
"textwrap",
]
[[package]]
name = "ruff_python"
version = "0.0.244"
dependencies = [
"once_cell",
"regex",
"rustc-hash",
]
[[package]]
name = "rust-stemmers"
version = "1.2.0"
@@ -2062,16 +2045,16 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.36.7"
version = "0.36.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@@ -2089,17 +2072,16 @@ dependencies = [
[[package]]
name = "rustpython-ast"
version = "0.2.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=4f38cb68e4a97aeea9eb19673803a0bd5f655383#4f38cb68e4a97aeea9eb19673803a0bd5f655383"
source = "git+https://github.com/RustPython/RustPython.git?rev=adc23253e4b58980b407ba2760dbe61681d752fc#adc23253e4b58980b407ba2760dbe61681d752fc"
dependencies = [
"num-bigint",
"rustpython-common",
"rustpython-compiler-core",
]
[[package]]
name = "rustpython-common"
version = "0.2.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=4f38cb68e4a97aeea9eb19673803a0bd5f655383#4f38cb68e4a97aeea9eb19673803a0bd5f655383"
source = "git+https://github.com/RustPython/RustPython.git?rev=adc23253e4b58980b407ba2760dbe61681d752fc#adc23253e4b58980b407ba2760dbe61681d752fc"
dependencies = [
"ascii",
"bitflags",
@@ -2124,7 +2106,7 @@ dependencies = [
[[package]]
name = "rustpython-compiler-core"
version = "0.2.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=4f38cb68e4a97aeea9eb19673803a0bd5f655383#4f38cb68e4a97aeea9eb19673803a0bd5f655383"
source = "git+https://github.com/RustPython/RustPython.git?rev=adc23253e4b58980b407ba2760dbe61681d752fc#adc23253e4b58980b407ba2760dbe61681d752fc"
dependencies = [
"bincode",
"bitflags",
@@ -2141,7 +2123,7 @@ dependencies = [
[[package]]
name = "rustpython-parser"
version = "0.2.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=4f38cb68e4a97aeea9eb19673803a0bd5f655383#4f38cb68e4a97aeea9eb19673803a0bd5f655383"
source = "git+https://github.com/RustPython/RustPython.git?rev=adc23253e4b58980b407ba2760dbe61681d752fc#adc23253e4b58980b407ba2760dbe61681d752fc"
dependencies = [
"ahash",
"anyhow",
@@ -2151,8 +2133,8 @@ dependencies = [
"log",
"num-bigint",
"num-traits",
"phf 0.10.1",
"phf_codegen 0.10.0",
"phf",
"phf_codegen",
"rustc-hash",
"rustpython-ast",
"rustpython-compiler-core",
@@ -2286,9 +2268,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.91"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a"
dependencies = [
"itoa",
"ryu",
@@ -2297,9 +2279,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c68e921cef53841b8925c2abadd27c9b891d9613bdc43d6b823062866df38e8"
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
dependencies = [
"serde",
]
@@ -2455,8 +2437,8 @@ dependencies = [
"dirs",
"fnv",
"nom",
"phf 0.11.1",
"phf_codegen 0.11.1",
"phf",
"phf_codegen",
]
[[package]]
@@ -2568,9 +2550,9 @@ dependencies = [
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "titlecase"
@@ -2606,9 +2588,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.18.0"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581"
checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
dependencies = [
"indexmap",
"nom8",
@@ -2758,19 +2740,6 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "update-informer"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "152ff185ca29f7f487c51ca785b0f1d85970c4581f4cdd12ed499227890200f5"
dependencies = [
"directories",
"semver",
"serde",
"serde_json",
"ureq",
]
[[package]]
name = "ureq"
version = "2.6.2"
@@ -2782,8 +2751,6 @@ dependencies = [
"log",
"once_cell",
"rustls",
"serde",
"serde_json",
"url",
"webpki",
"webpki-roots",
@@ -2802,9 +2769,9 @@ dependencies = [
[[package]]
name = "uuid"
version = "1.2.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
[[package]]
name = "version_check"
@@ -2852,9 +2819,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -2862,9 +2829,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log",
@@ -2877,9 +2844,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.33"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
dependencies = [
"cfg-if",
"js-sys",
@@ -2889,9 +2856,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2899,9 +2866,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
@@ -2912,15 +2879,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.33"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b"
dependencies = [
"console_error_panic_hook",
"js-sys",
@@ -2932,9 +2899,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.33"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9"
dependencies = [
"proc-macro2",
"quote",
@@ -2942,9 +2909,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.60"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -3032,6 +2999,30 @@ dependencies = [
"windows_x86_64_msvc",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"

View File

@@ -1,88 +1,6 @@
[workspace]
members = [
"flake8_to_ruff",
"ruff_dev",
"ruff_cli",
]
default-members = [".", "ruff_cli"]
[package]
name = "ruff"
version = "0.0.240"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
edition = "2021"
rust-version = "1.65.0"
documentation = "https://github.com/charliermarsh/ruff"
homepage = "https://github.com/charliermarsh/ruff"
repository = "https://github.com/charliermarsh/ruff"
readme = "README.md"
license = "MIT"
[lib]
name = "ruff"
crate-type = ["cdylib", "rlib"]
doctest = false
[dependencies]
anyhow = { version = "1.0.66" }
bitflags = { version = "1.3.2" }
cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { version = "4.0.1", features = ["derive", "env"] }
colored = { version = "2.0.0" }
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" }
itertools = { version = "0.10.5" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
log = { version = "0.4.17" }
natord = { version = "1.0.9" }
nohash-hasher = { version = "0.2.0" }
num-bigint = { version = "0.4.3" }
num-traits = "0.2.15"
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
regex = { version = "1.6.0" }
ruff_macros = { version = "0.0.240", path = "ruff_macros" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
schemars = { version = "0.8.11" }
semver = { version = "1.0.16" }
serde = { version = "1.0.147", features = ["derive"] }
shellexpand = { version = "3.0.0" }
smallvec = { version = "1.10.0" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
textwrap = { version = "0.16.0" }
thiserror = { version = "1.0" }
titlecase = { version = "2.2.1" }
toml = { version = "0.6.0" }
# 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" }
members = ["crates/*"]
default-members = ["crates/ruff", "crates/ruff_cli"]
[profile.release]
panic = "abort"

576
README.md
View File

@@ -7,8 +7,9 @@
[![image](https://img.shields.io/pypi/l/ruff.svg)](https://pypi.python.org/pypi/ruff)
[![image](https://img.shields.io/pypi/pyversions/ruff.svg)](https://pypi.python.org/pypi/ruff)
[![Actions status](https://github.com/charliermarsh/ruff/workflows/CI/badge.svg)](https://github.com/charliermarsh/ruff/actions)
[![image](https://img.shields.io/date/1676394000?label=Jetbrains%20Ruff%20Webinar&logo=jetbrains)](https://info.jetbrains.com/PyCharm-Webinar-February14-2023.html)
[**Discord**](https://discord.gg/Z8KbeK24) | [**Docs**](https://beta.ruff.rs/docs/) | [**Playground**](https://play.ruff.rs/)
[**Discord**](https://discord.gg/c9MhzV8aU5) | [**Docs**](https://beta.ruff.rs/docs/) | [**Playground**](https://play.ruff.rs/)
An extremely fast Python linter, written in Rust.
@@ -24,16 +25,16 @@ 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`
- 🤝 Python 3.11 compatibility
- 🛠️ `pyproject.toml` support
- 📦 Built-in caching, to avoid re-analyzing unchanged files
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
- ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
- 🔌 Native re-implementations of dozens of Flake8 plugins, like [flake8-bugbear](https://pypi.org/project/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`
* 🤝 Python 3.11 compatibility
* 🛠️ `pyproject.toml` support
* 📦 Built-in caching, to avoid re-analyzing unchanged files
* 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
* ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
* 🔌 Native re-implementations of dozens of Flake8 plugins, like [flake8-bugbear](https://pypi.org/project/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)
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
functionality behind a single, common interface.
@@ -46,32 +47,32 @@ 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)
- [Apache Airflow](https://github.com/apache/airflow)
- [SciPy](https://github.com/scipy/scipy)
- [Bokeh](https://github.com/bokeh/bokeh)
- [Zulip](https://github.com/zulip/zulip)
- [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)
- [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)
- [Saleor](https://github.com/saleor/saleor)
- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
- [Home Assistant](https://github.com/home-assistant/core)
- [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)
* [pandas](https://github.com/pandas-dev/pandas)
* [FastAPI](https://github.com/tiangolo/fastapi)
* [Apache Airflow](https://github.com/apache/airflow)
* [SciPy](https://github.com/scipy/scipy)
* [Bokeh](https://github.com/bokeh/bokeh)
* [Zulip](https://github.com/zulip/zulip)
* [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)
* [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)
* [Saleor](https://github.com/saleor/saleor)
* [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
* [Home Assistant](https://github.com/home-assistant/core)
* [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)
Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster) or
the most recent [project update](https://notes.crmarsh.com/ruff-the-first-200-releases).
@@ -89,7 +90,7 @@ co-creator of [GraphQL](https://graphql.org/):
> Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On
> our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4
> cores on my M1. Running ruff against our *entire* codebase takes .4 seconds.
> cores on my M1. Running ruff against our _entire_ codebase takes .4 seconds.
[**Bryan Van de Ven**](https://github.com/bokeh/bokeh/pull/12605), co-creator
of [Bokeh](https://github.com/bokeh/bokeh/), original author
@@ -164,7 +165,6 @@ This README is also available as [documentation](https://beta.ruff.rs/docs/).
1. [FAQ](#faq)
1. [Contributing](#contributing)
1. [Support](#support)
1. [Benchmarks](#benchmarks)
1. [Reference](#reference)
1. [License](#license)
@@ -213,16 +213,16 @@ apk add ruff
To run Ruff, try any of the following:
```shell
ruff . # Lint all files in the current directory (and any subdirectories)
ruff path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories)
ruff path/to/code/*.py # Lint all `.py` files in `/path/to/code`
ruff path/to/code/to/file.py # Lint `file.py`
ruff check . # Lint all files in the current directory (and any subdirectories)
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories)
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 path/to/code/ --watch
ruff check path/to/code/ --watch
```
Ruff also works with [pre-commit](https://pre-commit.com):
@@ -230,7 +230,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
```yaml
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.0.240'
rev: 'v0.0.244'
hooks:
- id: ruff
```
@@ -340,13 +340,13 @@ 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
* 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,
* 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,
* 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](#ruff-tried-to-fix-something-but-it-broke-my-code-what-should-i-do)).
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
@@ -377,13 +377,14 @@ Some configuration settings can be provided via the command-line, such as those
rule enablement and disablement, file discovery, logging level, and more:
```shell
ruff path/to/code/ --select F401 --select F403 --quiet
ruff check path/to/code/ --select F401 --select F403 --quiet
```
See `ruff help` for more on Ruff's top-level commands:
<!-- Begin auto-generated command help. -->
```
```text
Ruff: An extremely fast Python linter.
Usage: ruff [OPTIONS] <COMMAND>
@@ -406,12 +407,14 @@ Log levels:
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]...
@@ -472,14 +475,15 @@ Miscellaneous:
The name of the file when passing it through stdin
-e, --exit-zero
Exit with status code "0", even upon detecting lint violations
--update-check
Enable or disable automatic update checks
--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
@@ -531,7 +535,7 @@ By default, Ruff will also skip any files that are omitted via `.ignore`, `.giti
`.git/info/exclude`, and global `gitignore` files (see: [`respect-gitignore`](#respect-gitignore)).
Files that are passed to `ruff` directly are always linted, regardless of the above criteria.
For example, `ruff /path/to/excluded/file.py` will always lint `file.py`.
For example, `ruff check /path/to/excluded/file.py` will always lint `file.py`.
### Rule resolution
@@ -555,9 +559,9 @@ select = ["E", "F"]
ignore = ["F401"]
```
Running `ruff --select F401` would result in Ruff enforcing `F401`, and no other rules.
Running `ruff check --select F401` would result in Ruff enforcing `F401`, and no other rules.
Running `ruff --extend-select B` would result in Ruff enforcing the `E`, `F`, and `B` rules, with
Running `ruff check --extend-select B` would result in Ruff enforcing the `E`, `F`, and `B` rules, with
the exception of `F401`.
### Suppressing errors
@@ -602,15 +606,15 @@ 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 /path/to/file.py --extend-select RUF100` to flag unused `noqa`
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 /path/to/file.py --extend-select RUF100 --fix` to automatically remove unused
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 /path/to/file.py --add-noqa` to automatically
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
@@ -623,6 +627,25 @@ 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.
<!-- End section: Configuration -->
## Supported Rules
@@ -639,6 +662,7 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
<!-- Sections automatically generated by `cargo dev generate-rules-table`. -->
<!-- Begin auto-generated sections. -->
### Pyflakes (F)
For more, see [Pyflakes](https://pypi.org/project/pyflakes/) on PyPI.
@@ -694,6 +718,7 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/) on PyPI.
For more, see [pycodestyle](https://pypi.org/project/pycodestyle/) on PyPI.
#### Error (E)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| E101 | mixed-spaces-and-tabs | Indentation contains mixed spaces and tabs | |
@@ -714,6 +739,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/) on PyPI.
| E999 | syntax-error | SyntaxError: {message} | |
#### Warning (W)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| W292 | no-new-line-at-end-of-file | No newline at end of file | 🛠 |
@@ -852,6 +878,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/) on PyPI.
| UP034 | extraneous-parentheses | Avoid extraneous parentheses | 🛠 |
| UP035 | import-replacements | Import from `{module}` instead: {names} | 🛠 |
| UP036 | outdated-version-block | Version block is outdated for minimum Python version | 🛠 |
| UP037 | quoted-annotation | Remove quotes from type annotation | 🛠 |
### flake8-2020 (YTT)
@@ -951,7 +978,7 @@ For more, see [flake8-bugbear](https://pypi.org/project/flake8-bugbear/) on PyPI
| B014 | duplicate-handler-exception | Exception handler with duplicate exception: `{name}` | 🛠 |
| B015 | useless-comparison | Pointless comparison. This comparison does nothing but waste CPU instructions. Either prepend `assert` or remove it. | |
| B016 | cannot-raise-literal | Cannot raise a literal. Did you intend to return it or raise an Exception? | |
| B017 | no-assert-raises-exception | `assertRaises(Exception)` should be considered evil | |
| [B017](https://github.com/charliermarsh/ruff/blob/main/docs/rules/assert-raises-exception.md) | [assert-raises-exception](https://github.com/charliermarsh/ruff/blob/main/docs/rules/assert-raises-exception.md) | `assertRaises(Exception)` should be considered evil | |
| B018 | useless-expression | Found useless expression. Either assign it to a variable or remove it. | |
| B019 | cached-instance-method | Use of `functools.lru_cache` or `functools.cache` on methods can lead to memory leaks | |
| B020 | loop-variable-overrides-iterator | Loop control variable `{name}` overrides iterable it iterates | |
@@ -1070,7 +1097,7 @@ For more, see [flake8-import-conventions](https://github.com/joaopalmeiro/flake8
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| ICN001 | import-alias-is-not-conventional | `{name}` should be imported as `{asname}` | |
| [ICN001](https://github.com/charliermarsh/ruff/blob/main/docs/rules/unconventional-import-alias.md) | [unconventional-import-alias](https://github.com/charliermarsh/ruff/blob/main/docs/rules/unconventional-import-alias.md) | `{name}` should be imported as `{asname}` | |
### flake8-logging-format (G)
@@ -1093,7 +1120,7 @@ For more, see [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420/) on
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| INP001 | implicit-namespace-package | File `{filename}` is part of an implicit namespace package. Add an `__init__.py`. | |
| [INP001](https://github.com/charliermarsh/ruff/blob/main/docs/rules/implicit-namespace-package.md) | [implicit-namespace-package](https://github.com/charliermarsh/ruff/blob/main/docs/rules/implicit-namespace-package.md) | File `{filename}` is part of an implicit namespace package. Add an `__init__.py`. | |
### flake8-pie (PIE)
@@ -1107,6 +1134,7 @@ For more, see [flake8-pie](https://pypi.org/project/flake8-pie/) on PyPI.
| PIE800 | no-unnecessary-spread | Unnecessary spread `**` | |
| PIE804 | no-unnecessary-dict-kwargs | Unnecessary `dict` kwargs | |
| PIE807 | prefer-list-builtin | Prefer `list` over useless lambda | 🛠 |
| PIE810 | single-starts-ends-with | Call `{attr}` once with a `tuple` | |
### flake8-print (T20)
@@ -1114,8 +1142,8 @@ For more, see [flake8-print](https://pypi.org/project/flake8-print/) on PyPI.
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| T201 | print-found | `print` found | 🛠 |
| T203 | p-print-found | `pprint` found | 🛠 |
| T201 | print-found | `print` found | |
| T203 | p-print-found | `pprint` found | |
### flake8-pytest-style (PT)
@@ -1155,10 +1183,10 @@ For more, see [flake8-quotes](https://pypi.org/project/flake8-quotes/) on PyPI.
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| Q000 | bad-quotes-inline-string | Double quotes found but single quotes preferred | 🛠 |
| Q001 | bad-quotes-multiline-string | Double quote multiline found but single quotes preferred | 🛠 |
| Q002 | bad-quotes-docstring | Double quote docstring found but single quotes preferred | 🛠 |
| Q003 | avoid-quote-escape | Change outer quotes to avoid escaping inner quotes | 🛠 |
| [Q000](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-inline-string.md) | [bad-quotes-inline-string](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-inline-string.md) | Double quotes found but single quotes preferred | 🛠 |
| [Q001](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-multiline-string.md) | [bad-quotes-multiline-string](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-multiline-string.md) | Double quote multiline found but single quotes preferred | 🛠 |
| [Q002](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-docstring.md) | [bad-quotes-docstring](https://github.com/charliermarsh/ruff/blob/main/docs/rules/bad-quotes-docstring.md) | Double quote docstring found but single quotes preferred | 🛠 |
| [Q003](https://github.com/charliermarsh/ruff/blob/main/docs/rules/avoid-quote-escape.md) | [avoid-quote-escape](https://github.com/charliermarsh/ruff/blob/main/docs/rules/avoid-quote-escape.md) | Change outer quotes to avoid escaping inner quotes | 🛠 |
### flake8-return (RET)
@@ -1226,7 +1254,7 @@ For more, see [flake8-type-checking](https://pypi.org/project/flake8-type-checki
| TCH002 | typing-only-third-party-import | Move third-party import `{}` into a type-checking block | |
| TCH003 | typing-only-standard-library-import | Move standard library import `{}` into a type-checking block | |
| TCH004 | runtime-import-in-type-checking-block | Move import `{}` out of type-checking block. Import is used for more than type hinting. | |
| TCH005 | empty-type-checking-block | Found empty type-checking block | |
| TCH005 | empty-type-checking-block | Found empty type-checking block | 🛠 |
### flake8-unused-arguments (ARG)
@@ -1278,7 +1306,7 @@ For more, see [eradicate](https://pypi.org/project/eradicate/) on PyPI.
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| ERA001 | commented-out-code | Found commented-out code | 🛠 |
| [ERA001](https://github.com/charliermarsh/ruff/blob/main/docs/rules/commented-out-code.md) | [commented-out-code](https://github.com/charliermarsh/ruff/blob/main/docs/rules/commented-out-code.md) | Found commented-out code | 🛠 |
### pandas-vet (PD)
@@ -1315,12 +1343,14 @@ For more, see [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) on GitH
For more, see [Pylint](https://pypi.org/project/pylint/) on PyPI.
#### Convention (PLC)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLC0414 | useless-import-alias | Import alias does not rename original package | 🛠 |
| PLC3002 | unnecessary-direct-lambda-call | Lambda expression called directly. Execute the expression inline instead. | |
#### Error (PLE)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLE0117 | nonlocal-without-binding | Nonlocal name `{name}` found without binding | |
@@ -1328,20 +1358,26 @@ For more, see [Pylint](https://pypi.org/project/pylint/) on PyPI.
| PLE0604 | invalid-all-object | Invalid object in `__all__`, must contain only strings | |
| PLE0605 | invalid-all-format | Invalid format for `__all__`, must be `tuple` or `list` | |
| PLE1142 | await-outside-async | `await` should be used within an async function | |
| PLE1310 | bad-str-strip-call | String `{strip}` call contains duplicate characters (did you mean `{removal}`?) | |
| PLE2502 | bidirectional-unicode | Avoid using bidirectional unicode | |
#### Refactor (PLR)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLR0133 | constant-comparison | Two constants compared in a comparison, consider replacing `{left_constant} {op} {right_constant}` | |
| PLR0133 | comparison-of-constant | Two constants compared in a comparison, consider replacing `{left_constant} {op} {right_constant}` | |
| PLR0206 | property-with-parameters | Cannot have defined parameters for properties | |
| PLR0402 | consider-using-from-import | Use `from {module} import {name}` in lieu of alias | |
| PLR0913 | too-many-args | Too many arguments to function call ({c_args}/{max_args}) | |
| PLR0402 | consider-using-from-import | Use `from {module} import {name}` in lieu of alias | 🛠 |
| PLR0911 | too-many-return-statements | Too many return statements ({returns}/{max_returns}) | |
| PLR0912 | too-many-branches | Too many branches ({branches}/{max_branches}) | |
| PLR0913 | too-many-arguments | Too many arguments to function call ({c_args}/{max_args}) | |
| PLR0915 | too-many-statements | Too many statements ({statements}/{max_statements}) | |
| PLR1701 | consider-merging-isinstance | Merge these isinstance calls: `isinstance({obj}, ({types}))` | |
| PLR1722 | use-sys-exit | Use `sys.exit()` instead of `{name}` | 🛠 |
| PLR1722 | consider-using-sys-exit | Use `sys.exit()` instead of `{name}` | 🛠 |
| PLR2004 | magic-value-comparison | Magic value used in comparison, consider replacing {value} with a constant variable | |
#### Warning (PLW)
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLW0120 | useless-else-on-loop | Else clause on loop without a break statement, remove the else and de-indent all the code inside it | |
@@ -1353,7 +1389,7 @@ For more, see [tryceratops](https://pypi.org/project/tryceratops/1.1.0/) on PyPI
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| TRY002 | raise-vanilla-class | Create your own exception | |
| [TRY002](https://github.com/charliermarsh/ruff/blob/main/docs/rules/raise-vanilla-class.md) | [raise-vanilla-class](https://github.com/charliermarsh/ruff/blob/main/docs/rules/raise-vanilla-class.md) | Create your own exception | |
| TRY003 | raise-vanilla-args | Avoid specifying long messages outside the exception class | |
| TRY004 | prefer-type-error | Prefer `TypeError` exception for invalid type | 🛠 |
| TRY200 | reraise-no-cause | Use `raise from` to specify exception cause | |
@@ -1368,7 +1404,7 @@ For more, see [flake8-raise](https://pypi.org/project/flake8-raise/) on PyPI.
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | |
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | 🛠 |
### flake8-self (SLF)
@@ -1402,7 +1438,7 @@ For more, see [flake8-self](https://pypi.org/project/flake8-self/) on PyPI.
Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff),
which supports autofix actions, import sorting, and more.
![](https://user-images.githubusercontent.com/1309177/205175763-cf34871d-5c05-4abf-9916-440afc82dbf8.gif)
![Ruff VS Code extension](https://user-images.githubusercontent.com/1309177/205175763-cf34871d-5c05-4abf-9916-440afc82dbf8.gif)
### Language Server Protocol (Official)
@@ -1547,13 +1583,14 @@ let g:ale_fixers = {
```yaml
tools:
python-ruff: &python-ruff
lint-command: 'ruff --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}'
lint-command: "ruff check --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}"
lint-stdin: true
lint-formats:
- '%f:%l:%c: %m'
format-command: 'ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -'
- "%f:%l:%c: %m"
format-command: "ruff check --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -"
format-stdin: true
```
</details>
<details>
@@ -1570,8 +1607,8 @@ null_ls.setup({
}
})
```
</details>
</details>
### PyCharm (External Tool)
@@ -1612,7 +1649,7 @@ jobs:
pip install ruff
# Include `--format=github` to enable automatic inline annotations.
- name: Run Ruff
run: ruff --format=github .
run: ruff check --format=github .
```
<!-- End section: Editor Integrations -->
@@ -1644,47 +1681,47 @@ implements all of the `F` rules (which originate from Pyflakes), along with a su
Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools
natively, including:
- [autoflake](https://pypi.org/project/autoflake/) ([#1647](https://github.com/charliermarsh/ruff/issues/1647))
- [eradicate](https://pypi.org/project/eradicate/)
- [flake8-2020](https://pypi.org/project/flake8-2020/)
- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
- [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
- [flake8-builtins](https://pypi.org/project/flake8-builtins/)
- [flake8-commas](https://pypi.org/project/flake8-commas/)
- [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
- [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
- [flake8-debugger](https://pypi.org/project/flake8-debugger/)
- [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
- [flake8-executable](https://pypi.org/project/flake8-executable/)
- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
- [flake8-pie](https://pypi.org/project/flake8-pie/)
- [flake8-print](https://pypi.org/project/flake8-print/)
- [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
- [flake8-raise](https://pypi.org/project/flake8-raise/)
- [flake8-return](https://pypi.org/project/flake8-return/)
- [flake8-self](https://pypi.org/project/flake8-self/)
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
- [flake8-super](https://pypi.org/project/flake8-super/)
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
- [isort](https://pypi.org/project/isort/)
- [mccabe](https://pypi.org/project/mccabe/)
- [pandas-vet](https://pypi.org/project/pandas-vet/)
- [pep8-naming](https://pypi.org/project/pep8-naming/)
- [pydocstyle](https://pypi.org/project/pydocstyle/)
- [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
- [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827))
- [yesqa](https://github.com/asottile/yesqa)
* [autoflake](https://pypi.org/project/autoflake/) ([#1647](https://github.com/charliermarsh/ruff/issues/1647))
* [eradicate](https://pypi.org/project/eradicate/)
* [flake8-2020](https://pypi.org/project/flake8-2020/)
* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
* [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
* [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
* [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
* [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
* [flake8-builtins](https://pypi.org/project/flake8-builtins/)
* [flake8-commas](https://pypi.org/project/flake8-commas/)
* [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
* [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
* [flake8-debugger](https://pypi.org/project/flake8-debugger/)
* [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
* [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
* [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
* [flake8-executable](https://pypi.org/project/flake8-executable/)
* [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
* [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
* [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
* [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
* [flake8-pie](https://pypi.org/project/flake8-pie/)
* [flake8-print](https://pypi.org/project/flake8-print/)
* [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
* [flake8-quotes](https://pypi.org/project/flake8-quotes/)
* [flake8-raise](https://pypi.org/project/flake8-raise/)
* [flake8-return](https://pypi.org/project/flake8-return/)
* [flake8-self](https://pypi.org/project/flake8-self/)
* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
* [flake8-super](https://pypi.org/project/flake8-super/)
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
* [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
* [isort](https://pypi.org/project/isort/)
* [mccabe](https://pypi.org/project/mccabe/)
* [pandas-vet](https://pypi.org/project/pandas-vet/)
* [pep8-naming](https://pypi.org/project/pep8-naming/)
* [pydocstyle](https://pypi.org/project/pydocstyle/)
* [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
* [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827))
* [yesqa](https://github.com/asottile/yesqa)
Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the
originating Flake8 plugins. For example, Ruff uses `TID252` to represent the `I252` rule from
@@ -1700,8 +1737,8 @@ Beyond the rule set, Ruff suffers from the following limitations vis-à-vis Flak
There are a few other minor incompatibilities between Ruff and the originating Flake8 plugins:
- Ruff doesn't implement all the "opinionated" lint rules from flake8-bugbear.
- Depending on your project structure, Ruff and isort can differ in their detection of first-party
* Ruff doesn't implement all the "opinionated" lint rules from flake8-bugbear.
* Depending on your project structure, Ruff and isort can differ in their detection of first-party
code. (This is often solved by modifying the `src` property, e.g., to `src = ["src"]`, if your
code is nested in a `src` directory.)
@@ -1743,41 +1780,41 @@ feedback on type errors.
Today, Ruff can be used to replace Flake8 when used with any of the following plugins:
- [flake8-2020](https://pypi.org/project/flake8-2020/)
- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
- [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
- [flake8-builtins](https://pypi.org/project/flake8-builtins/)
- [flake8-commas](https://pypi.org/project/flake8-commas/)
- [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
- [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
- [flake8-debugger](https://pypi.org/project/flake8-debugger/)
- [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
- [flake8-executable](https://pypi.org/project/flake8-executable/)
- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
- [flake8-pie](https://pypi.org/project/flake8-pie/)
- [flake8-print](https://pypi.org/project/flake8-print/)
- [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
- [flake8-raise](https://pypi.org/project/flake8-raise/)
- [flake8-return](https://pypi.org/project/flake8-return/)
- [flake8-self](https://pypi.org/project/flake8-self/)
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
- [flake8-super](https://pypi.org/project/flake8-super/)
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
- [mccabe](https://pypi.org/project/mccabe/)
- [pandas-vet](https://pypi.org/project/pandas-vet/)
- [pep8-naming](https://pypi.org/project/pep8-naming/)
- [pydocstyle](https://pypi.org/project/pydocstyle/)
* [flake8-2020](https://pypi.org/project/flake8-2020/)
* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
* [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
* [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
* [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
* [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
* [flake8-builtins](https://pypi.org/project/flake8-builtins/)
* [flake8-commas](https://pypi.org/project/flake8-commas/)
* [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
* [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
* [flake8-debugger](https://pypi.org/project/flake8-debugger/)
* [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
* [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
* [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
* [flake8-executable](https://pypi.org/project/flake8-executable/)
* [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
* [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
* [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
* [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
* [flake8-pie](https://pypi.org/project/flake8-pie/)
* [flake8-print](https://pypi.org/project/flake8-print/)
* [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
* [flake8-quotes](https://pypi.org/project/flake8-quotes/)
* [flake8-raise](https://pypi.org/project/flake8-raise/)
* [flake8-return](https://pypi.org/project/flake8-return/)
* [flake8-self](https://pypi.org/project/flake8-self/)
* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
* [flake8-super](https://pypi.org/project/flake8-super/)
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
* [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
* [mccabe](https://pypi.org/project/mccabe/)
* [pandas-vet](https://pypi.org/project/pandas-vet/)
* [pep8-naming](https://pypi.org/project/pep8-naming/)
* [pydocstyle](https://pypi.org/project/pydocstyle/)
Ruff can also replace [isort](https://pypi.org/project/isort/),
[yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/),
@@ -1878,7 +1915,7 @@ matter how they're provided, which avoids accidental incompatibilities and simpl
### How can I tell what settings Ruff is using to check my code?
Run `ruff /path/to/code.py --show-settings` to view the resolved settings for a given file.
Run `ruff check /path/to/code.py --show-settings` to view the resolved settings for a given file.
### I want to use Ruff, but I don't want to use `pyproject.toml`. Is that possible?
@@ -1944,137 +1981,14 @@ If you find a case where Ruff's autofix breaks your code, please file an Issue!
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/Z8KbeK24).
can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
## Support
Having trouble? Check out the existing issues on [**GitHub**](https://github.com/charliermarsh/ruff/issues),
or feel free to [**open a new one**](https://github.com/charliermarsh/ruff/issues/new).
You can also ask for help on [**Discord**](https://discord.gg/Z8KbeK24).
## Benchmarks
First, clone [CPython](https://github.com/python/cpython). It's a large and diverse Python codebase,
which makes it a good target for benchmarking.
```shell
git clone --branch 3.10 https://github.com/python/cpython.git resources/test/cpython
```
To benchmark the release build:
```shell
cargo build --release && hyperfine --ignore-failure --warmup 10 \
"./target/release/ruff ./resources/test/cpython/ --no-cache" \
"./target/release/ruff ./resources/test/cpython/"
Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
Time (mean ± σ): 293.8 ms ± 3.2 ms [User: 2384.6 ms, System: 90.3 ms]
Range (min … max): 289.9 ms … 301.6 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: ./target/release/ruff ./resources/test/cpython/
Time (mean ± σ): 48.0 ms ± 3.1 ms [User: 65.2 ms, System: 124.7 ms]
Range (min … max): 45.0 ms … 66.7 ms 62 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./resources/test/cpython/' ran
6.12 ± 0.41 times faster than './target/release/ruff ./resources/test/cpython/ --no-cache'
```
To benchmark against the ecosystem's existing tools:
```shell
hyperfine --ignore-failure --warmup 5 \
"./target/release/ruff ./resources/test/cpython/ --no-cache" \
"pyflakes resources/test/cpython" \
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
"pycodestyle resources/test/cpython" \
"flake8 resources/test/cpython"
Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
Time (mean ± σ): 294.3 ms ± 3.3 ms [User: 2467.5 ms, System: 89.6 ms]
Range (min … max): 291.1 ms … 302.8 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: pyflakes resources/test/cpython
Time (mean ± σ): 15.786 s ± 0.143 s [User: 15.560 s, System: 0.214 s]
Range (min … max): 15.640 s … 16.157 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s]
Range (min … max): 5.950 s … 6.391 s 10 runs
Benchmark 4: pycodestyle resources/test/cpython
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s]
Range (min … max): 46.171 s … 47.863 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 5: flake8 resources/test/cpython
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s]
Range (min … max): 11.848 s … 12.933 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./resources/test/cpython/ --no-cache' ran
20.98 ± 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
41.66 ± 1.18 times faster than 'flake8 resources/test/cpython'
53.64 ± 0.77 times faster than 'pyflakes resources/test/cpython'
159.43 ± 2.48 times faster than 'pycodestyle resources/test/cpython'
```
You can run `poetry install` from `./scripts` to create a working environment for the above. All
reported benchmarks were computed using the versions specified by `./scripts/pyproject.toml`
on Python 3.11.
To benchmark Pylint, remove the following files from the CPython repository:
```shell
rm Lib/test/bad_coding.py \
Lib/test/bad_coding2.py \
Lib/test/bad_getattr.py \
Lib/test/bad_getattr2.py \
Lib/test/bad_getattr3.py \
Lib/test/badcert.pem \
Lib/test/badkey.pem \
Lib/test/badsyntax_3131.py \
Lib/test/badsyntax_future10.py \
Lib/test/badsyntax_future3.py \
Lib/test/badsyntax_future4.py \
Lib/test/badsyntax_future5.py \
Lib/test/badsyntax_future6.py \
Lib/test/badsyntax_future7.py \
Lib/test/badsyntax_future8.py \
Lib/test/badsyntax_future9.py \
Lib/test/badsyntax_pep3120.py \
Lib/test/test_asyncio/test_runners.py \
Lib/test/test_copy.py \
Lib/test/test_inspect.py \
Lib/test/test_typing.py
```
Then, from `resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
will execute Pylint with maximum parallelism and only report errors.
To benchmark Pyupgrade, run the following from `resources/test/cpython`:
```shell
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \
"find . -type f -name \"*.py\" | xargs -P 0 pyupgrade --py311-plus"
Benchmark 1: find . -type f -name "*.py" | xargs -P 0 pyupgrade --py311-plus
Time (mean ± σ): 30.119 s ± 0.195 s [User: 28.638 s, System: 0.390 s]
Range (min … max): 29.813 s … 30.356 s 10 runs
```
You can also ask for help on [**Discord**](https://discord.gg/c9MhzV8aU5).
## Reference
@@ -2084,6 +1998,7 @@ Benchmark 1: find . -type f -name "*.py" | xargs -P 0 pyupgrade --py311-plus
<!-- Sections automatically generated by `cargo dev generate-options`. -->
<!-- Begin auto-generated options sections. -->
#### [`allowed-confusables`](#allowed-confusables)
A list of allowed "confusable" Unicode characters to ignore when
@@ -2174,10 +2089,10 @@ A list of file patterns to exclude from linting.
Exclusions are based on globs, and can be either:
- Single-path patterns, like `.mypy_cache` (to exclude any directory
* Single-path patterns, like `.mypy_cache` (to exclude any directory
named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
`foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
- Relative patterns, like `directory/foo.py` (to exclude that specific
* Relative patterns, like `directory/foo.py` (to exclude that specific
file) or `directory/*.py` (to exclude any Python files in
`directory`). Note that these paths are relative to the project root
(e.g., the directory containing your `pyproject.toml`).
@@ -2233,10 +2148,10 @@ specified by `exclude`.
Exclusions are based on globs, and can be either:
- Single-path patterns, like `.mypy_cache` (to exclude any directory
* Single-path patterns, like `.mypy_cache` (to exclude any directory
named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
`foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
- Relative patterns, like `directory/foo.py` (to exclude that specific
* Relative patterns, like `directory/foo.py` (to exclude that specific
file) or `directory/*.py` (to exclude any Python files in
`directory`). Note that these paths are relative to the project root
(e.g., the directory containing your `pyproject.toml`).
@@ -2357,8 +2272,8 @@ fix-only = true
#### [`fixable`](#fixable)
A list of rule codes or prefixes to consider autofixable. By default, all rules are
considered autofixable.
A list of rule codes or prefixes to consider autofixable. By default,
all rules are considered autofixable.
**Default value**: `["A", "ANN", "ARG", "B", "BLE", "C", "COM", "D", "DTZ", "E", "EM", "ERA", "EXE", "F", "FBT", "G", "I", "ICN", "INP", "ISC", "N", "PD", "PGH", "PIE", "PL", "PT", "PTH", "Q", "RET", "RUF", "S", "SIM", "T", "TCH", "TID", "TRY", "UP", "W", "YTT"]`
@@ -2769,6 +2684,25 @@ allow-star-arg-any = true
---
#### [`ignore-fully-untyped`](#ignore-fully-untyped)
Whether to suppress `ANN*` rules for any declaration
that hasn't been typed at all.
This makes it easier to gradually add types to a codebase.
**Default value**: `false`
**Type**: `bool`
**Example usage**:
```toml
[tool.ruff.flake8-annotations]
ignore-fully-untyped = true
```
---
#### [`mypy-init-return`](#mypy-init-return)
Whether to allow the omission of a return type hint for `__init__` if at
@@ -2810,8 +2744,8 @@ suppress-dummy-args = true
Whether to suppress `ANN200`-level violations for functions that meet
either of the following criteria:
- Contain no `return` statement.
- Explicit `return` statement(s) all return `None` (explicitly or
* Contain no `return` statement.
* Explicit `return` statement(s) all return `None` (explicitly or
implicitly).
**Default value**: `false`
@@ -2831,8 +2765,9 @@ suppress-none-returning = true
#### [`check-typed-exception`](#check-typed-exception)
Whether to disallow `try`-`except`-`pass` (`S110`) for specific exception types. By default,
`try`-`except`-`pass` is only disallowed for `Exception` and `BaseException`.
Whether to disallow `try`-`except`-`pass` (`S110`) for specific
exception types. By default, `try`-`except`-`pass` is only
disallowed for `Exception` and `BaseException`.
**Default value**: `false`
@@ -3063,6 +2998,7 @@ mark-parentheses = true
Expected type for multiple argument names in `@pytest.mark.parametrize`.
The following values are supported:
* `csv` — a comma-separated list, e.g.
`@pytest.mark.parametrize('name1,name2', ...)`
* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
@@ -3086,6 +3022,7 @@ parametrize-names-type = "list"
Expected type for each row of values in `@pytest.mark.parametrize` in
case of multiple parameters. The following values are supported:
* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
[(1, 2), (3, 4)])`
* `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2],
@@ -3108,6 +3045,7 @@ parametrize-values-row-type = "list"
Expected type for the list of values rows in `@pytest.mark.parametrize`.
The following values are supported:
* `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))`
* `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`
@@ -3307,7 +3245,7 @@ exempt-modules = ["typing", "typing_extensions"]
Enforce TC001, TC002, and TC003 rules even when valid runtime imports
are present for the same module.
See: https://github.com/snok/flake8-type-checking#strict.
See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.
**Default value**: `false`
@@ -3851,7 +3789,8 @@ allow-magic-value-types = ["int"]
#### [`max-args`](#max-args)
Maximum number of arguments allowed for a function definition (see: `PLR0913`).
Maximum number of arguments allowed for a function or method definition
(see: `PLR0913`).
**Default value**: `5`
@@ -3866,9 +3805,46 @@ max-args = 5
---
#### [`max-branches`](#max-branches)
Maximum number of branches allowed for a function or method body (see:
`PLR0912`).
**Default value**: `12`
**Type**: `int`
**Example usage**:
```toml
[tool.ruff.pylint]
max-branches = 12
```
---
#### [`max-returns`](#max-returns)
Maximum number of return statements allowed for a function or method
body (see `PLR0911`)
**Default value**: `6`
**Type**: `int`
**Example usage**:
```toml
[tool.ruff.pylint]
max-returns = 6
```
---
#### [`max-statements`](#max-statements)
Maximum number of statements allowed for a method or a statement (see: `PLR0915`).
Maximum number of statements allowed for a function or method body (see:
`PLR0915`).
**Default value**: `50`

2
_typos.toml Normal file
View File

@@ -0,0 +1,2 @@
[files]
extend-exclude = ["snapshots"]

View File

@@ -1,6 +1,6 @@
[package]
name = "flake8-to-ruff"
version = "0.0.240"
version = "0.0.244"
edition = "2021"
[dependencies]
@@ -10,14 +10,10 @@ colored = { version = "2.0.0" }
configparser = { version = "3.0.2" }
once_cell = { version = "1.16.0" }
regex = { version = "1.6.0" }
ruff = { path = "..", default-features = false }
ruff = { path = "../ruff", default-features = false }
rustc-hash = { version = "1.1.0" }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = { version = "1.0.87" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
toml = { version = "0.6.0" }
[dev-dependencies]
[features]

View File

@@ -1,25 +1,13 @@
//! Utility to generate Ruff's `pyproject.toml` section from a Flake8 INI file.
#![forbid(unsafe_code)]
#![warn(clippy::pedantic)]
#![allow(
clippy::collapsible_else_if,
clippy::collapsible_if,
clippy::implicit_hasher,
clippy::match_same_arms,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::similar_names,
clippy::too_many_lines
)]
use std::path::PathBuf;
use anyhow::Result;
use clap::Parser;
use configparser::ini::Ini;
use ruff::flake8_to_ruff::{self, ExternalConfig};
use ruff::logging::{set_up_logging, LogLevel};
#[derive(Parser)]
#[command(
@@ -41,6 +29,8 @@ struct Args {
}
fn main() -> Result<()> {
set_up_logging(&LogLevel::Default)?;
let args = Args::parse();
// Read the INI file.
@@ -61,7 +51,11 @@ fn main() -> Result<()> {
// Create Ruff's pyproject.toml section.
let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?;
println!("{}", toml::to_string_pretty(&pyproject)?);
#[allow(clippy::print_stdout)]
{
println!("{}", toml::to_string_pretty(&pyproject)?);
}
Ok(())
}

82
crates/ruff/Cargo.toml Normal file
View File

@@ -0,0 +1,82 @@
[package]
name = "ruff"
version = "0.0.244"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
edition = "2021"
rust-version = "1.65.0"
documentation = "https://github.com/charliermarsh/ruff"
homepage = "https://github.com/charliermarsh/ruff"
repository = "https://github.com/charliermarsh/ruff"
readme = "README.md"
license = "MIT"
[lib]
name = "ruff"
crate-type = ["cdylib", "rlib"]
doctest = false
[dependencies]
anyhow = { version = "1.0.66" }
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"] }
clap = { version = "4.0.1", features = ["derive", "env"] }
colored = { version = "2.0.0" }
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" }
itertools = { version = "0.10.5" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
log = { version = "0.4.17" }
natord = { version = "1.0.9" }
nohash-hasher = { version = "0.2.0" }
num-bigint = { version = "0.4.3" }
num-traits = "0.2.15"
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
regex = { version = "1.6.0" }
ruff_macros = { version = "0.0.244", path = "../ruff_macros" }
ruff_python = { version = "0.0.244", path = "../ruff_python" }
rustc-hash = { version = "1.1.0" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
schemars = { version = "0.8.11" }
semver = { version = "1.0.16" }
serde = { version = "1.0.147", features = ["derive"] }
shellexpand = { version = "3.0.0" }
smallvec = { version = "1.10.0" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
textwrap = { version = "0.16.0" }
thiserror = { version = "1.0" }
titlecase = { version = "2.2.1" }
toml = { version = "0.6.0" }
# 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" }
[features]
default = []
logical_lines = []

View File

@@ -0,0 +1,44 @@
"""Test case expected to be run with `ignore_fully_untyped = True`."""
def ok_fully_untyped_1(a, b):
pass
def ok_fully_untyped_2():
pass
def ok_fully_typed_1(a: int, b: int) -> int:
pass
def ok_fully_typed_2() -> int:
pass
def ok_fully_typed_3(a: int, *args: str, **kwargs: str) -> int:
pass
def error_partially_typed_1(a: int, b):
pass
def error_partially_typed_2(a: int, b) -> int:
pass
def error_partially_typed_3(a: int, b: int):
pass
class X:
def ok_untyped_method_with_arg(self, a):
pass
def ok_untyped_method(self):
pass
def error_typed_self(self: X):
pass

View File

@@ -53,3 +53,8 @@ def foo():
return True
else:
return
# Error (on the argument, but not the return type)
def foo(a):
a = 2 + 2

View File

@@ -57,3 +57,12 @@ dict.fromkeys(("world",), True)
{}.deploy(True, False)
getattr(someobj, attrname, False)
mylist.index(True)
class Registry:
def __init__(self) -> None:
self._switches = [False] * len(Switch)
# FBT001: Boolean positional arg in function definition
def __setitem__(self, switch: Switch, value: bool) -> None:
self._switches[switch.value] = value

View File

@@ -44,4 +44,45 @@ for foo, bar in [(1, 2)]:
print(FMT.format(**vars()))
for foo, bar in [(1, 2)]:
print(FMT.format(foo=foo, bar=eval('bar')))
print(FMT.format(foo=foo, bar=eval("bar")))
def f():
# Fixable.
for foo, bar, baz in (["1", "2", "3"],):
if foo or baz:
break
def f():
# Unfixable due to usage of `bar` outside of loop.
for foo, bar, baz in (["1", "2", "3"],):
if foo or baz:
break
print(bar)
def f():
# Fixable.
for foo, bar, baz in (["1", "2", "3"],):
if foo or baz:
break
bar = 1
def f():
# Fixable.
for foo, bar, baz in (["1", "2", "3"],):
if foo or baz:
break
bar = 1
print(bar)
# Unfixable due to trailing underscore (`_line_` wouldn't be considered an ignorable
# variable name).
for line_ in range(self.header_lines):
fp.readline()

Some files were not shown because too many files have changed in this diff Show More