Compare commits

..

1116 Commits

Author SHA1 Message Date
Charlie Marsh
6e97c9438a Merge branch 'main' into github-2923 2023-03-02 15:55:55 -05:00
Charlie Marsh
187104e396 Flag out-of-date docs on CI (#3309) 2023-03-02 15:55:39 -05:00
Charlie Marsh
ea86edf12e Rename, etc. 2023-03-02 15:50:10 -05:00
Martin Kagamino Lehoux
2558384817 Replace tuples with type union in isinstance or issubclass calls (#2923) 2023-03-02 21:07:00 +01:00
Charlie Marsh
3ed539d50e Add a CLI flag to force-ignore noqa directives (#3296) 2023-03-01 22:28:13 -05:00
Charlie Marsh
4a70a4c323 Ignore unused imports in ModuleNotFoundError blocks (#3288) 2023-03-01 18:08:37 -05:00
Charlie Marsh
310f13c7db Redirect RUF004 to B026 (#3293) 2023-03-01 13:00:02 -05:00
konstin
2168404fc2 flake8-pyi PYI006 bad version info comparison (#3291)
Implement PYI006 "bad version info comparison"

## What it does

Ensures that you only `<` and `>=` for version info comparisons with
`sys.version_info` in `.pyi` files. All other comparisons such as
`<`, `<=` and `==` are banned.

## Why is this bad?

```python
>>> import sys
>>> print(sys.version_info)
sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)
>>> print(sys.version_info > (3, 8))
True
>>> print(sys.version_info == (3, 8))
False
>>> print(sys.version_info <= (3, 8))
False
>>> print(sys.version_info in (3, 8))
False
```

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-03-01 18:58:57 +01:00
Charlie Marsh
a032b66c2e Avoid PEP 585 rewrites when builtins are shadowed (#3286) 2023-02-28 23:25:42 +00:00
Charlie Marsh
af5f7dbd83 Avoid pluralization for single --add-noqa result (#3282) 2023-02-28 15:41:18 -05:00
Charlie Marsh
8066607ea3 Add a preliminary tutorial (#3281) 2023-02-28 20:31:27 +00:00
Andy Freeland
0ed9fccce9 Upgrade RustPython (#3277)
Fixes #3207.
2023-02-28 12:21:28 -05:00
Carlos Gonçalves
074a343a63 feat(E251,E252): add rules (#3274) 2023-02-28 12:02:36 -05:00
Charlie Marsh
c7e09b54b0 Use expression span for yoda-conditions fixes (#3276) 2023-02-28 16:59:02 +00:00
Charlie Marsh
67d1f74587 Avoid raising TRY200 violations within new scopes (#3275) 2023-02-28 11:56:29 -05:00
Matthew Lloyd
1c79dff3bd Improve the message for PLW2901: use "outer" and "inner" judiciously (#3263) 2023-02-28 16:33:01 +00:00
Charlie Marsh
f5f09b489b Introduce dedicated CST tokens for other operator kinds (#3267) 2023-02-27 23:54:57 -05:00
Charlie Marsh
061495a9eb Make BoolOp its own located token (#3265) 2023-02-28 03:43:28 +00:00
Charlie Marsh
470e1c1754 Preserve comments on non-defaulted arguments (#3264) 2023-02-27 23:41:40 +00:00
Charlie Marsh
16be691712 Enable more non-panicking formatter tests (#3262) 2023-02-27 18:21:53 -05:00
Charlie Marsh
270015865b Don't flag keyword-based logging format strings (#3261) 2023-02-27 23:11:13 +00:00
Charlie Marsh
ccfa9d5b20 Deduplicate SIM116 errors (#3260) 2023-02-27 18:08:45 -05:00
Charlie Marsh
2261e194a0 Create dedicated Body nodes in the formatter CST (#3223) 2023-02-27 22:55:05 +00:00
Ville Skyttä
cd6413ca09 Match non-lowercase with S105 again (#3258) 2023-02-27 16:38:23 -05:00
Charlie Marsh
c65585e14a Use identifier_range for a few more rules (#3254) 2023-02-27 18:23:33 +00:00
Charlie Marsh
d2a6ed7be6 Upgrade RustPython (#3252) 2023-02-27 18:21:06 +00:00
Charlie Marsh
16e2dae0c2 Handle empty NamedTuple and TypedDict conversions (#3251) 2023-02-27 11:18:34 -05:00
Carlos Gonçalves
e8ba9c9e21 feat(W191): add indentation_contains_tabs (#3249) 2023-02-27 10:36:03 -05:00
Jonathan Plasse
d285f5c90a Run automatically format code blocks with Black (#3191) 2023-02-27 10:14:05 -05:00
Charlie Marsh
386ca7c9a1 Bump version to 0.0.253 (#3245) 2023-02-26 23:10:04 -05:00
Charlie Marsh
40c5abf16e Avoid flagging Pylint logging rules with starred arguments (#3244) 2023-02-26 22:58:24 -05:00
Matthew Lloyd
7e7aec7d74 Expand the range of the COM812 autofix to include the preceding token (#3241)
This prevents the UP034 autofix simultaneously stripping the
parentheses from generators in the same linter pass, which causes
a SyntaxError.

Closes #3234.

With this fix:

```python
$ cat test.py
the_first_one = next(
    (i for i in range(10) if i // 2 == 0)
)

$ cargo run --bin ruff check test.py --no-cache --select UP034,COM812 --fix
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/ruff check test.py --no-cache --select UP034,COM812 --fix`
Found 1 error (1 fixed, 0 remaining).

$ cat test.py
the_first_one = next(
    i for i in range(10) if i // 2 == 0
)
```

* Use format

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-02-27 03:47:07 +00:00
Ivan Gozali
4b5538f74e [pylint] W0603: global-statement (#3227)
Implements pylint rule [W0603: global-statement](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/global-statement.html).

Currently checks for global statement usage in a few StmtKinds (as tested in the `pylint` `global-statement` test case [here](b70d2abd7f/tests/functional/g/globals.py)):

* Assign
* AugAssign
* ClassDef
* FunctionDef | AsyncFunctionDef
* Import
* ImportFrom
* Delete
2023-02-26 23:40:24 +00:00
Charlie Marsh
36d134fd41 Bump lint rule count to 500+ (#3240) 2023-02-26 18:10:09 -05:00
Chris Chan
0b7d6b9097 Implement pylint's else-if-used rule (PLR5501) (#3231)
Attempt to implement else-if-used
https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/else-if-used.html

Issue #970
2023-02-26 22:42:33 +00:00
Nick Pope
994e2e0903 Rename some flake8-simplify rules (#2915)
Renames the following rules that stood out to me at a glance as needing better names:

- `or-true` to `expr-or-true`
- `and-false` to `expr-and-false`
- `a-or-not-a` to `expr-or-not-expr`
- `a-and-not-a` to `expr-and-not-expr`

Related to #2902.
2023-02-26 22:35:15 +00:00
Luc Khai Hai
bc79f540e4 [flake8-django] DJ003, DJ006, DJ007 (#3236)
Implements [flake8-django](https://github.com/rocioar/flake8-django) rules:
- DJ03
- DJ06
- DJ07
2023-02-26 22:29:42 +00:00
Steve Dignam
3a78b59314 [flake8-pyi]: PYI011, PYI014 (#3238)
Implement PYI011 and PYI014 with the latest changes:

https://github.com/PyCQA/flake8-pyi/pull/326
https://github.com/PyCQA/flake8-pyi/issues/316

rel: https://github.com/charliermarsh/ruff/issues/848
rel: 4212bec43d/pyi.py (L718)
2023-02-26 22:11:58 +00:00
Edgar R. M
5f83851329 [pydocstyle]: Implement ignore-decorators (#3229) 2023-02-26 21:40:01 +00:00
Carlos Gonçalves
484ce7b8fc feat(E275): add Missing whitespace after keyword (#3225) 2023-02-26 21:36:05 +00:00
Charlie Marsh
1c75071136 Implement basic rendering of remaining AST nodes (#3233) 2023-02-26 05:05:56 +00:00
Charlie Marsh
51bca19c1d Add builders for common comment rendering (#3232) 2023-02-26 04:16:24 +00:00
Steve Dignam
a8a312e862 [flake8-pyi]: PYI009, PYI010, PYI021 (#3230)
PYI009 and PYI010 are very similar, always use `...` in function and class bodies in stubs.

PYI021 bans doc strings in stubs.

I think all of these rules should be relatively straightforward to implement auto fixes for but can do that later once we get all the other rules added.

rel: https://github.com/charliermarsh/ruff/issues/848
2023-02-25 22:29:04 -05:00
Ran Benita
33c31cda27 Add noqa_row to diagnostics JSON format (#3228)
In ruff-lsp (https://github.com/charliermarsh/ruff-lsp/pull/76) we want to add a "Disable \<rule\> for this line" quickfix. However, finding the correct line into which the `noqa` comment should be inserted is non-trivial (multi-line strings for example).

Ruff already has this info, so expose it in the JSON output for use by ruff-lsp.
2023-02-25 18:13:16 -05:00
Edgar R. M
cd9fbeb560 [bandit]: Do not treat "passed" as "password" for S105/S106/S107 (#3222) 2023-02-25 15:32:53 -05:00
Jeong YunWon
84e96cdcd9 More enum work (#3212) 2023-02-25 11:40:16 -05:00
Charlie Marsh
248590224a Avoid flagging logging-too-few-args with no arguments (#3220) 2023-02-24 21:57:49 -05:00
Charlie Marsh
bbc55cdb04 Allow ruff.toml file to be dot-prefixed (as .ruff.toml) (#3221) 2023-02-24 23:14:26 +00:00
Charlie Marsh
2792439eac Add TextMate to editor-integrations.md (#3219) 2023-02-24 22:57:33 +00:00
Charlie Marsh
0694aee1b6 Avoid EXE001 and EXE002 errors from stdin input (#3218) 2023-02-24 22:55:32 +00:00
Charlie Marsh
a17b5c134a Avoid rewriting any PEP 604 runtime annotations (#3217)
Following `pyupgrade`, we'll just _never_ touch these.

Closes #2981.

Closes #3215.
2023-02-24 22:39:58 +00:00
Charlie Marsh
42f61535b5 Normalize treatment of aliased and unaliased imports (#3216) 2023-02-24 22:11:03 +00:00
Carlos Gonçalves
1c01b3c934 fix(docs): broken links inside Configuration.md (#3205) 2023-02-24 18:55:33 +00:00
Jonathan Plasse
39b9a1637f Fix Markdown errors in docs (#3187) 2023-02-24 13:06:48 -05:00
Jonathan Plasse
2c692e3acf Remove --all from cargo fmt|test (#3208) 2023-02-24 12:52:59 -05:00
monosans
24add5f56c Avoid boolean-trap rules for ConfigParser get() methods (#3209) 2023-02-24 12:52:33 -05:00
Samuel Cormier-Iijima
0b7736ad79 [flake8-tidy-imports] fix autofix for relative imports (#3197) 2023-02-23 23:40:28 -05:00
Charlie Marsh
eef85067c8 Exclude globsets for --show-settings (#3201) 2023-02-24 04:23:00 +00:00
Jeong YunWon
da98fab4ae Adapt is-macro for a few enums (#3182) 2023-02-24 04:06:56 +00:00
Charlie Marsh
0f37a98d91 Use then-some pattern for sometimes-fixable rules (#3199) 2023-02-24 03:57:14 +00:00
Charlie Marsh
f38624824d Avoid autofixing some PT violations when comments are present (#3198) 2023-02-24 03:48:41 +00:00
Charlie Marsh
159422071e Handle end-of-line comments on excepthandler and alias (#3196) 2023-02-23 22:35:39 -05:00
Charlie Marsh
6eaacf96be Introduce a new CST element for slice segments (#3195) 2023-02-24 00:49:41 +00:00
Charlie Marsh
eb15371453 Make Locator available in AST-to-CST conversion pass (#3194) 2023-02-23 19:43:03 -05:00
Matt Nawara
198b301baf [pycodestyle] trailing-whitespace, blank-line-contains-whitespace (W291, W293) (#3122) 2023-02-23 19:04:45 -05:00
Jeong YunWon
c8c575dd43 Adapt BoolLike to flags (#3175) 2023-02-23 16:31:46 -05:00
Jonathan Plasse
6e54cd8233 Normalize relative markdown links (#3190) 2023-02-23 16:24:31 -05:00
Jonathan Plasse
a688a237d7 Add black to pre-commit (#3192) 2023-02-23 16:24:23 -05:00
Charlie Marsh
bda2a0007a Parenthesize numbers during attribute accesses (#3189) 2023-02-23 14:57:23 -05:00
Charlie Marsh
32d165b7ad Implement complex literal formatting (#3186) 2023-02-23 19:09:33 +00:00
Charlie Marsh
ac79bf4ee9 Implement float literal formatting (#3184) 2023-02-23 14:02:23 -05:00
Charlie Marsh
376eab3a53 Implement integer literal formatting (#3183) 2023-02-23 18:31:56 +00:00
Charlie Marsh
08be7bd285 Add a TODO to string_literal (#3181) 2023-02-23 12:46:20 -05:00
Charlie Marsh
f5241451d8 Use writeln with --show-settings (#3180) 2023-02-23 17:23:31 +00:00
Charlie Marsh
c9fe0708cb Run cargo update (#3179) 2023-02-23 12:09:36 -05:00
Charlie Marsh
09f8c487ea Update RustPython to support *tuple annotations (#3178) 2023-02-23 16:58:38 +00:00
Charlie Marsh
1e7233a8eb Add support for reformatting byte strings (#3176) 2023-02-23 16:50:24 +00:00
Charlie Marsh
f967f344fc Add support for basic Constant::Str formatting (#3173)
This PR enables us to apply the proper quotation marks, including support for escapes. There are some significant TODOs, especially around implicit concatenations like:

```py
(
  "abc"
  "def"
)
```

Which are represented as a single AST node, which requires us to tokenize _within_ the formatter to identify all the individual string parts.
2023-02-23 16:23:10 +00:00
Charlie Marsh
095f005bf4 Move RustPython vendored and helper code into its own crate (#3171) 2023-02-23 14:14:16 +00:00
Charlie Marsh
0f04aa2a5f Bind star patterns in match statements (#3169) 2023-02-23 12:39:03 +00:00
Jonathan Plasse
ad7ba77fff Fix ExceptionGroup F821 false positive (#3167) 2023-02-23 12:36:11 +00:00
Jeong YunWon
77d43795f8 Replace Autofix::is_enabled to result_like::BoolLike (#3165) 2023-02-23 07:29:13 -05:00
Jeong YunWon
4357f2be0f Add Autofix::is_enabled() to remove repeative patterns (#3159) 2023-02-22 23:52:07 -05:00
Charlie Marsh
e5c1f95545 Check-in updated snapshot (#3161) 2023-02-23 03:42:27 +00:00
Charlie Marsh
227ff62a4e Don't touch tuple brackets after in (#3160) 2023-02-23 03:10:24 +00:00
Charlie Marsh
d8e4902516 Un-modify tupleassign and function2 tests (#3158)
I manually changed these in #3080 and #3083 to get the tests passing (with notes around the deviations) -- but that's no longer necessary, now that we have proper testing that takes deviations into account.
2023-02-23 02:37:25 +00:00
Matthew Lloyd
e66739884f Add note about prioritizing naming convention over preservation (#3157) 2023-02-23 02:32:46 +00:00
Charlie Marsh
5fd827545b Add a trailing newline to all .py.expect files (#3156)
This just re-formats all the `.py.expect` files with Black, both to add a trailing newline and be doubly-certain that they're correctly formatted.

I also ensured that we add a hard line break after each statement, and that we avoid including an extra newline in the generated Markdown (since the code should contain the exact expected newlines).
2023-02-23 02:29:27 +00:00
Matthew Lloyd
c1ddcb8a60 [flake8-pie] Unnecessary list comprehension, with autofix (PIE802) (#3149) 2023-02-22 20:58:45 -05:00
Charlie Marsh
48a317d5f6 Change via to using (#3155) 2023-02-23 01:47:15 +00:00
Charlie Marsh
74e18b6cff Split up some docs sections (#3154) 2023-02-22 20:18:10 -05:00
Charlie Marsh
21d02cd51f Omit non-.py[i] files from module naming rules (#3153) 2023-02-23 00:38:46 +00:00
Charlie Marsh
049e77b939 Follow-up with some small doc changes (#3152) 2023-02-23 00:35:22 +00:00
Charlie Marsh
b9bfb81e36 Move configuration out of README and into permanent docs (#3150) 2023-02-22 19:25:53 -05:00
Charlie Marsh
2d4fae45d9 Avoid flagging unfixable TypedDict and NamedTuple definitions (#3148) 2023-02-22 23:23:25 +00:00
Charlie Marsh
726adb7efc Avoid suggesting 'is' for constant literals (#3146) 2023-02-22 22:37:22 +00:00
Charlie Marsh
dbdfdeb0e1 Add pre-commit note to docs (#3145) 2023-02-22 17:22:47 -05:00
Charlie Marsh
1c41789c2a Bump version to 0.0.252 (#3142) 2023-02-22 14:50:14 -05:00
Charlie Marsh
2f9de335db Upgrade RustPython to match new flattened exports (#3141) 2023-02-22 19:36:13 +00:00
Ran Benita
ba61bb6a6c Fix isort no-lines-before preceded by an empty section (#3139)
Fix isort no-lines-before preceded by an empty section

Fix #3138.
2023-02-22 14:35:53 -05:00
Charlie Marsh
17ab71ff75 Include match in nested block check (#3137) 2023-02-22 14:32:08 -05:00
Charlie Marsh
4ad4e3e091 Avoid useless-else-on-loop for break within match (#3136) 2023-02-22 19:12:44 +00:00
Florian Best
6ced5122e4 refactor(use-from-import): build fixed variant via AST (#3132) 2023-02-22 13:17:37 -05:00
Marijn Valk
7d55b417f7 add delta-rs to list of users (#3133) 2023-02-22 13:07:58 -05:00
Charlie Marsh
f0e0efc46f Upgrade RustPython to handle trailing commas in map patterns (#3130) 2023-02-22 11:17:13 -05:00
Charlie Marsh
1efa2e07ad Avoid match statement misidentification in token rules (#3129) 2023-02-22 15:44:45 +00:00
Charlie Marsh
df3932f750 Use file-specific quote for C408 (#3128) 2023-02-22 15:26:46 +00:00
Rupert Tombs
817d0b4902 Fix =/== error in ManualDictLookup (#3117) 2023-02-22 15:14:30 +00:00
Micha Reiser
ffd8e958fc chore: Upgrade Rust to 1.67.0 (#3125) 2023-02-22 10:03:17 -05:00
Micha Reiser
ed33b75bad test(ruff_python_formatter): Run all Black tests (#2993)
This PR changes the testing infrastructure to run all black tests and:

* Pass if Ruff and Black generate the same formatting
* Fail and write a markdown snapshot that shows the input code, the differences between Black and Ruff, Ruffs output, and Blacks output

This is achieved by introducing a new `fixture` macro (open to better name suggestions) that "duplicates" the attributed test for every file that matches the specified glob pattern. Creating a new test for each file over having a test that iterates over all files has the advantage that you can run a single test, and that test failures indicate which case is failing. 

The `fixture` macro also makes it straightforward to e.g. setup our own spec tests that test very specific formatting by creating a new folder and use insta to assert the formatted output.
2023-02-22 09:25:06 -05:00
Micha Reiser
262e768fd3 refactor(ruff): Implement doc_lines_from_tokens as iterator (#3124)
This is a nit refactor... It implements the extraction of document lines as an iterator instead of a Vector to avoid the extra allocation.
2023-02-22 09:22:06 -05:00
Ran Benita
bc3a9ce003 Mark typing.assert_never as no return (#3121)
This function always raises, so RET503 shouldn't trigger for it.
2023-02-22 09:15:39 -05:00
Charlie Marsh
48005d87f8 Add missing backticks from rustdoc (#3112) 2023-02-22 05:03:06 +00:00
Charlie Marsh
e37e9c2ca3 Skip EXE001 and EXE002 rules on Windows (#3111) 2023-02-21 23:39:56 -05:00
Matthieu Devlin
8fde63b323 [pylint] Implement E1205 and E106 (#3084) 2023-02-21 22:53:11 -05:00
Matthew Lloyd
97338e4cd6 [pylint] redefined-loop-name (W2901) (#3022)
Slightly broadens W2901 to cover `with` statements too.

Closes #2972.
2023-02-22 03:23:47 +00:00
Charlie Marsh
9645790a8b Support shell expansion for --config argument (#3107) 2023-02-21 23:33:41 +00:00
Charlie Marsh
18800c6884 Include file permissions in cache key (#3104) 2023-02-21 18:20:06 -05:00
Charlie Marsh
fd638a2e54 Bump version to 0.0.251 (#3105) 2023-02-21 18:13:59 -05:00
Charlie Marsh
fa1459d56e Avoid prefer-list-builtin for lambdas with *args or **kwargs (#3102) 2023-02-21 17:44:37 -05:00
Charlie Marsh
d93c5811ea Create bindings for MatchAs patterns (#3098) 2023-02-21 22:04:09 +00:00
Charlie Marsh
06e426f509 Bump version to 0.0.250 (#3095) 2023-02-21 15:20:46 -05:00
Carlos Gonçalves
6eb014b3b2 feat(B032): add b032 flake8_bugbear (#3085) 2023-02-21 19:53:29 +00:00
Charlie Marsh
d9fd78d907 Ignore setters in flake8-boolean-trap (#3092) 2023-02-21 19:31:00 +00:00
Charlie Marsh
37df07d2e0 Re-add compatibility to README (#3091) 2023-02-21 18:57:47 +00:00
Charlie Marsh
d5c65b5f1b Add support for structural pattern matching (#3047) 2023-02-21 18:52:10 +00:00
Charlie Marsh
cdc4e86158 Add support for TryStar (#3089) 2023-02-21 13:42:20 -05:00
Charlie Marsh
50ec6d3b0f Use LibCST to fix chained assertions (#3087) 2023-02-21 13:10:31 -05:00
Charlie Marsh
a6eb60cdd5 Enable function2 test (#3083) 2023-02-21 04:37:50 +00:00
Charlie Marsh
90c04b9cff Enable tupleassign test (#3080) 2023-02-21 00:42:23 +00:00
Charlie Marsh
b701cca779 Enable some already-passing Black tests (#3079) 2023-02-21 00:10:35 +00:00
Charlie Marsh
ce8953442d Add support for trailing colons in slice expressions (#3077) 2023-02-20 23:24:32 +00:00
Charlie Marsh
7d4e513a82 Omit while-True loops from implicit return enforcement (#3076) 2023-02-20 18:22:28 -05:00
Charlie Marsh
35f7f7b66d Avoid boolean-trap rules for positional-only builtin calls (#3075) 2023-02-20 23:08:18 +00:00
Charlie Marsh
6e02405bd6 Add StmtKind::Try; fix trailing newlines (#3074) 2023-02-20 22:55:32 +00:00
Carlos Gonçalves
b657468346 feat(B029): Add B029 from flake8-bugbear (#3068) 2023-02-20 15:57:13 -05:00
Micha Reiser
f72ed255e5 chore: Use LF on all platforms (#3005)
I worked on #2993 and ran into issues that the formatter tests are failing on Windows because `writeln!` emits `\n` as line terminator on all platforms, but `git` on Windows converted the line endings in the snapshots to `\r\n`.

I then tried to replicate the issue on my Windows machine and was surprised that all linter snapshot tests are failing on my machine. I figured out after some time that it is due to my global git config keeping the input line endings rather than converting to `\r\n`. 

Luckily, I've been made aware of #2033 which introduced an "override" for the `assert_yaml_snapshot` macro that normalizes new lines, by splitting the formatted string using the platform-specific newline character. This is a clever approach and gives nice diffs for multiline fixes but makes assumptions about the setup contributors use and requires special care whenever we use line endings inside of tests. 

I recommend that we remove the special new line handling and use `.gitattributes` to enforce the use of `LF` on all platforms [guide](https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings). This gives us platform agnostic tests without having to worry about line endings in our tests or different git configurations.

## Note

It may be necessary for Windows contributors to run the following command to update the line endings of their files

```bash
git rm --cached -r .
git reset --hard
```
2023-02-20 20:13:37 +00:00
Charlie Marsh
7e9dea0027 Change contributing suggestion (#3067) 2023-02-20 20:05:38 +00:00
Colin Delahunty
9545958ad8 [flake8-simplify]: Implement manual-dict-lookup (#2767) 2023-02-20 20:00:59 +00:00
Colin Delahunty
41faa335d1 [tryceratops]: Verbose Log Messages (#3036) 2023-02-20 18:21:04 +00:00
Charlie Marsh
4cfa350112 Bump version to 0.0.249 (#3063) 2023-02-20 13:11:29 -05:00
Charlie Marsh
41f163fc8d Avoid assert() to assert statement conversion in expressions (#3062) 2023-02-20 17:49:22 +00:00
Charlie Marsh
d21dd994e6 Increase expected size of FormatElement (#3049) 2023-02-20 12:47:35 -05:00
Josh Karpel
6f5a6b8c8b Do not autofix E731 in class bodies (#3050) 2023-02-20 12:38:42 -05:00
Jeong YunWon
35606d7b05 clean up to fix nightly clippy warnings and dedents (#3057) 2023-02-20 09:33:47 -05:00
Matthew Lloyd
3ad257cfea Add PDM to "Who's Using Ruff?" (#3048) 2023-02-20 03:58:22 +00:00
Charlie Marsh
b39f960cd1 Relax constraints on pep8-naming module validation (#3043) 2023-02-19 17:34:23 -05:00
Charlie Marsh
c297d46899 Remove unused AsFormat trait for Option<T> (#3041)
We should re-add this, but it's currently unused and doesn't compile under 1.66.0.

See: #3039.
2023-02-19 20:19:35 +00:00
Jonathan Plasse
d6a100028c Update docs and pre-commit after #3006 (#3038) 2023-02-19 14:23:01 -05:00
Jonathan Plasse
35d4e03f2a Fix ruff_dev regex workspace dependency (#3037) 2023-02-19 18:02:08 +00:00
Charlie Marsh
41e77bb01d Add some additional users to "Who's Using Ruff?" (#3035) 2023-02-19 16:30:01 +00:00
Charlie Marsh
2ff3dd5fbe Bump version to 0.0.248 (#3034) 2023-02-19 16:21:30 +00:00
Charlie Marsh
0f0e7a521a Avoid false-positives for break in with (#3032) 2023-02-19 11:17:04 -05:00
Jonathan Plasse
b75663be6d Add missing rust-version in crates (#3009) 2023-02-19 15:07:17 +00:00
Tomer Chachamu
4d3d04ee61 [PLE0101] error when __init__ returns a value (#3007) 2023-02-19 14:54:43 +00:00
Manuel Jacob
87422ba362 Add configuration option for C408 to allow dict calls with keyword arguments. (#2977)
When creating a dict with string keys, some prefer to call dict instead of writing a dict literal.
For example: `dict(a=1, b=2, c=3)` instead of `{"a": 1, "b": 2, "c": 3}`.
2023-02-19 14:47:03 +00:00
Jeremy Goh
c1d2976fff [docs] Add docs for flake8-implicit-str-concat rules (#3028) 2023-02-19 14:38:59 +00:00
Jeremy Goh
13281cd9ca [docs] Add some docs for flake8-simplify (#3027) 2023-02-19 14:26:56 +00:00
Jonathan Plasse
e53652779d Avoid raising B027 violations in .pyi files (#3016) 2023-02-19 14:21:33 +00:00
Jonathan Plasse
db4c611c6f Fix broken links and markdown style (#3017) 2023-02-19 08:46:49 -05:00
Charlie Marsh
c25be31eb1 Fix documentation-link detection in generate_mkdocs.py (#3030) 2023-02-19 12:20:44 +00:00
Micha Reiser
a7c533634d chore: Remove default_members from Cargo.toml (#3006)
This PR removes the `default_members` from the workspace configuration. 

## Why

I'm not familiar with the motivation for why the `default_members` setting was added initially, and I do not object to keeping it. I'll explain my motivation for removing it below. 

My main reason for removing the `default_members` override is that new contributors may not know that `cargo test`, `cargo build`, and other commands only run on a subset of crates. They may then be surprised that their PRs are failing in CI, but everything works locally. 

My guess why `default_members` was added is to speed up the development workflow. That's fair, but I question the value because `ruff` is the heaviest crate to build.
2023-02-19 07:18:47 -05:00
Simon Brugman
cfa6883431 docs(readme): add Diffusers (#3029) 2023-02-19 07:10:02 -05:00
Nyakku Shigure
216aa929af Remove duplicate underline in B007 autofix message (#3021) 2023-02-18 19:38:20 -05:00
Simon Brugman
9e45424ed6 [pycodestyle] autofix useless semicolons (#3001) 2023-02-17 18:52:42 -05:00
Charlie Marsh
db7f16e276 Support positional messages in assertion rewrites (#3002) 2023-02-17 23:44:13 +00:00
Charlie Marsh
a10a500a26 Ignore namedtuple methods in flake8-self (#2998) 2023-02-17 17:16:25 -05:00
Charlie Marsh
b9fef7cef7 Unlink flake8-bugbear in summary (#2997) 2023-02-17 15:58:33 -05:00
Charlie Marsh
34294ccc00 Deduplicate user list (#2996) 2023-02-17 20:07:42 +00:00
Simon Brugman
a934d01bdb [flake8-tidy-imports] extend autofix of relative imports (#2990)
This extends the autofix for TID252 to work with for relative imports without `module` (i.e. `from .. import`). Tested with `matplotlib` and `bokeh`.
(Previously it would panic on unwrap of the module) 

Note that pandas has [replaced](6057d7a93e) `absolufy-imports` with `ruff` now!
2023-02-17 19:35:28 +00:00
Simon Brugman
0dd590f137 Fix for F541 unescape f-string (#2971) 2023-02-17 14:27:01 -05:00
Charlie Marsh
909a5c3253 Avoid zero-indexed column for IOError (#2995) 2023-02-17 14:14:28 -05:00
Charlie Marsh
5c987874c4 Enforce D403 on methods (#2992) 2023-02-17 18:05:48 +00:00
Nyakku Shigure
0cfe4f9c69 Remove a whitespace in B004 message (#2991) 2023-02-17 12:37:08 -05:00
Charlie Marsh
6a369e4a30 Remove via from sentence in README (#2987) 2023-02-17 13:49:09 +00:00
Charlie Marsh
6f97e2c457 Split list of users into top-level and dedicated section (#2986) 2023-02-17 13:36:32 +00:00
Charlie Marsh
bebd412469 Adjust header depth in docs (#2985) 2023-02-17 13:19:55 +00:00
Charlie Marsh
cd1f57b713 Move FAQ into MkDocs (#2984) 2023-02-17 13:15:53 +00:00
Charlie Marsh
a0912deb2b Move editor integrations into MkDocs (#2983) 2023-02-17 13:12:20 +00:00
Charlie Marsh
50ee14a418 Fix references to specific settings in README.md (#2982) 2023-02-17 13:07:37 +00:00
Martin Fischer
f5adbbebc5 Fix table of contents enumeration 2023-02-17 07:55:50 -05:00
Martin Fischer
c88e05dc1b Merge Reference README section into Configuration section 2023-02-17 07:55:50 -05:00
Martin Fischer
d658bfc024 Remove options from README 2023-02-17 07:55:50 -05:00
Martin Fischer
b0d72c47b4 refactor: Move Top-level heading into ruff_dev 2023-02-17 07:55:50 -05:00
Martin Fischer
8195873cdf Remove rule tables from README 2023-02-17 07:55:50 -05:00
Martin Fischer
bf8108469f Remove auto-generated table of contents 2023-02-17 07:55:50 -05:00
Martin Fischer
a2277cfeba refactor: Move fix symbol legend into ruff_dev 2023-02-17 07:55:50 -05:00
Charlie Marsh
180541a924 Unify comment terminology with that of rome_formatter (#2979) 2023-02-17 03:02:25 +00:00
Simon Brugman
34664a0ca0 [numpy] numpy-legacy-random (#2960)
The new `Generator` in NumPy uses bits provided by [PCG64](https://numpy.org/doc/stable/reference/random/bit_generators/pcg64.html#numpy.random.PCG64) which has better statistical properties than the legacy [MT19937](https://numpy.org/doc/stable/reference/random/bit_generators/mt19937.html#numpy.random.MT19937) used in [RandomState](https://numpy.org/doc/stable/reference/random/legacy.html#numpy.random.RandomState). Global random functions can also be problematic with parallel processing.

This rule is probably quite useful for data scientists (perhaps in combination with `nbqa`)

References:
- [Legacy Random Generation](https://numpy.org/doc/stable/reference/random/legacy.html#legacy)
- [Random Sampling](https://numpy.org/doc/stable/reference/random/index.html#random-quick-start)
- [Using PyTorch + NumPy? You're making a mistake.](https://tanelp.github.io/posts/a-bug-that-plagues-thousands-of-open-source-ml-projects/)
2023-02-17 02:06:30 +00:00
Charlie Marsh
e081455b06 Add support for file-scoped noqa directives (#2978)
# Summary

This allows users to do things like:

```py
# ruff: noqa: F401
```

...to ignore all `F401` directives in a file. It's equivalent to `per-file-ignores`, but allows users to specify the behavior inline.

Note that Flake8 does _not_ support this, so we _don't_ respect `# flake8: noqa: F401`. (Flake8 treats that as equivalent to `# flake8: noqa`, so ignores _all_ errors in the file. I think all of [these usages](https://cs.github.com/?scopeName=All+repos&scope=&q=%22%23+flake8%3A+noqa%3A+%22) are probably mistakes!)

A couple notes on the details:

- If a user has `# ruff: noqa: F401` in the file, but also `# noqa: F401` on a line that would legitimately trigger an `F401` violation, we _do_ mark that as "unused" for `RUF100` purposes. This may be the wrong choice. The `noqa` is legitimately unused, but it's also not "wrong". It's just redundant.
- If a user has `# ruff: noqa: F401`, and runs `--add-noqa`, we _won't_ add `# noqa: F401` to any lines (which seems like the obvious right choice to me).

Closes #1054 (which has some extra pieces that I'll carve out into a separate issue).

Closes #2446.
2023-02-17 01:59:01 +00:00
Artem Mukhin
4f18fa6733 Add test case for '\u' prefix in B005 (#2976)
Based on #2958.
2023-02-16 19:45:29 -05:00
Charlie Marsh
6088a36cd3 Use line_suffix for end-of-line comments (#2975) 2023-02-16 18:37:40 -05:00
Charlie Marsh
66a162fa40 Handle non-from __future__ imports (#2974)
These are uncommon, but currently panic.

Closes #2967.
2023-02-16 22:56:03 +00:00
Mike Taves
e6722f92ed Add Rust Trove classifier (#2973) 2023-02-16 17:38:36 -05:00
Charlie Marsh
750c28868f Enable jemalloc on FreeBSD and NetBSD (#2965) 2023-02-16 15:21:34 -05:00
Charlie Marsh
5157f584ab Improve pow operator spacing (#2970)
Ensure that we add spaces to expressions like `foo.bar() ** 2`.
2023-02-16 15:17:32 -05:00
Charlie Marsh
1c01ec21cb Regenerate expected Black snapshots (#2968) 2023-02-16 19:39:17 +00:00
Manuel Jacob
879512742f Skip .pytype directory by default. (#2966)
Pytype stores .pyi files in .pytype that ruff shouldn’t check or touch.
2023-02-16 14:38:08 -05:00
Florian Best
a919041dda feat(isort): Implement isort.force_to_top (#2877) 2023-02-16 19:01:59 +00:00
Charlie Marsh
059601d968 Avoid trying to fix implicit returns with control flow (#2962) 2023-02-16 13:42:46 -05:00
Charlie Marsh
2ec1701543 Remove link in asyncio.create_task (#2963) 2023-02-16 17:50:56 +00:00
Charlie Marsh
370c3a5daf Remove mdcat dependency (#2959) 2023-02-16 12:09:37 -05:00
Charlie Marsh
fdcb78fd8c Avoid jemallocator on BSD (#2957) 2023-02-16 11:48:51 -05:00
Simon Brugman
2a744d24e5 docs: flake8-self remove unnecessary backticks (#2951) 2023-02-16 08:25:34 -05:00
Simon Brugman
cc30738148 Implement flake8-module-naming (#2855)
- Implement N999 (following flake8-module-naming) in pep8_naming
- Refactor pep8_naming: split rules.rs into file per rule
- Documentation for majority of the violations

Closes https://github.com/charliermarsh/ruff/issues/2734
2023-02-16 04:20:33 +00:00
Edgar R. M
147c6ff1db Exclude crates/ruff_python_formatter/resources from pre-commit check (#2947) 2023-02-15 22:56:42 -05:00
Charlie Marsh
036380e6a8 Fix add-required-import with multi-line offsets (#2946) 2023-02-16 03:24:55 +00:00
Charlie Marsh
b6587e51ee Use an enum to represent composition kind (#2945) 2023-02-15 22:14:00 -05:00
Simon Brugman
1bc37110d4 [flake8-pytest-style] autofix for composite-assertion (PT018) (#2732) 2023-02-16 00:36:07 +00:00
Lunarmagpie
28acdb76cf Add support for ensure_future for RUF006 (#2943) 2023-02-15 23:18:11 +00:00
Martin Fischer
7b09972c97 Merge convert-loop-to-any & convert-loop-to-all to reimplemented-builtin 2023-02-15 16:24:31 -05:00
Charlie Marsh
f8d46d09ef Implement asyncio-dangling-task to track asyncio.create_task calls (#2935)
This rule guards against `asyncio.create_task` usages of the form:

```py
asyncio.create_task(coordinator.ws_connect())  # Error
```

...which can lead to unexpected bugs due to the lack of a strong reference to the created task. See Will McGugan's blog post for reference: https://textual.textualize.io/blog/2023/02/11/the-heisenbug-lurking-in-your-async-code/.

Note that we can't detect issues like:

```py
def f():
    # Stored as `task`, but never used...
    task = asyncio.create_task(coordinator.ws_connect())
```

So that would be a false negative. But this catches the common case of failing to assign the task in any way.

Closes #2809.
2023-02-15 15:19:03 -05:00
Martin Fischer
294cd95c54 Update clap to fix ruff check --help description
My two clap bug fixes[1][2] have been merged and released
(see the change in README.md).

[1]: https://github.com/clap-rs/clap/pull/4710
[2]: https://github.com/clap-rs/clap/pull/4712
2023-02-15 13:30:06 -05:00
Charlie Marsh
d8e709648d Add Transformers to README (#2933) 2023-02-15 17:09:50 +00:00
Charlie Marsh
52cc4d6537 Deduplicate files provided on the command-line (#2931) 2023-02-15 12:08:34 -05:00
messense
08e9d12137 Upload ruff binaries to GitHub release (#2930) 2023-02-15 12:07:47 -05:00
Charlie Marsh
39fdc71b49 Bump version to 0.0.247 (#2932) 2023-02-15 12:06:58 -05:00
Charlie Marsh
6b0736cf4b Allow private accesses on current class (#2929) 2023-02-15 16:52:05 +00:00
Charlie Marsh
58269a918a Apply nullable-model-string-field to all classes (#2928) 2023-02-15 15:54:14 +00:00
Sawbez
9168a12679 [docs] flake8-self Private member access docs (#2912) 2023-02-15 15:42:38 +00:00
Charlie Marsh
cb971d3a48 Respect self as positional-only argument in annotation rules (#2927) 2023-02-15 15:25:17 +00:00
Charlie Marsh
57a5071b4e Rename some methods on Locator (#2926) 2023-02-15 10:21:49 -05:00
Charlie Marsh
976fe364d4 Remove setup.py (#2922) 2023-02-15 14:35:11 +00:00
messense
028c7855b2 Simplify release workflows (#2913)
* No need to build for PyPy since it only contains a binary so the platform tag is the same as CPython
* Update `maturin-action` location
2023-02-15 08:15:19 -05:00
Nick Pope
e5179f67fd Remove autogenerated docs/rules/*.md files (#2917) 2023-02-15 08:11:11 -05:00
Simon Brugman
c9c199dbca Remove testing resource introduced in #2891 (#2916) 2023-02-15 08:10:58 -05:00
Martin Fischer
70e378b736 Implement shell autocompletion for rule codes
For example:

    $ ruff check --select=EM<Tab>
    EM          -- flake8-errmsg
    EM10   EM1  --
    EM101       -- raw-string-in-exception
    EM102       -- f-string-in-exception
    EM103       -- dot-format-in-exception

(You will need to enable autocompletion as described
 in the Autocompletion section in the README.)

Fixes #2808.

(The --help help change in the README is due to a clap bug,
 for which I already submitted a fix:
 https://github.com/clap-rs/clap/pull/4710.)
2023-02-15 08:09:34 -05:00
Charlie Marsh
ca49b00e55 Add initial formatter implementation (#2883)
# Summary

This PR contains the code for the autoformatter proof-of-concept.

## Crate structure

The primary formatting hook is the `fmt` function in `crates/ruff_python_formatter/src/lib.rs`.

The current formatter approach is outlined in `crates/ruff_python_formatter/src/lib.rs`, and is structured as follows:

- Tokenize the code using the RustPython lexer.
- In `crates/ruff_python_formatter/src/trivia.rs`, extract a variety of trivia tokens from the token stream. These include comments, trailing commas, and empty lines.
- Generate the AST via the RustPython parser.
- In `crates/ruff_python_formatter/src/cst.rs`, convert the AST to a CST structure. As of now, the CST is nearly identical to the AST, except that every node gets a `trivia` vector. But we might want to modify it further.
- In `crates/ruff_python_formatter/src/attachment.rs`, attach each trivia token to the corresponding CST node. The logic for this is mostly in `decorate_trivia` and is ported almost directly from Prettier (given each token, find its preceding, following, and enclosing nodes, then attach the token to the appropriate node in a second pass).
- In `crates/ruff_python_formatter/src/newlines.rs`, normalize newlines to match Black’s preferences. This involves traversing the CST and inserting or removing `TriviaToken` values as we go.
- Call `format!` on the CST, which delegates to type-specific formatter implementations (e.g., `crates/ruff_python_formatter/src/format/stmt.rs` for `Stmt` nodes, and similar for `Expr` nodes; the others are trivial). Those type-specific implementations delegate to kind-specific functions (e.g., `format_func_def`).

## Testing and iteration

The formatter is being developed against the Black test suite, which was copied over in-full to `crates/ruff_python_formatter/resources/test/fixtures/black`.

The Black fixtures had to be modified to create `[insta](https://github.com/mitsuhiko/insta)`-compatible snapshots, which now exist in the repo.

My approach thus far has been to try and improve coverage by tackling fixtures one-by-one.

## What works, and what doesn’t

- *Most* nodes are supported at a basic level (though there are a few stragglers at time of writing, like `StmtKind::Try`).
- Newlines are properly preserved in most cases.
- Magic trailing commas are properly preserved in some (but not all) cases.
- Trivial leading and trailing standalone comments mostly work (although maybe not at the end of a file).
- Inline comments, and comments within expressions, often don’t work -- they work in a few cases, but it’s one-off right now. (We’re probably associating them with the “right” nodes more often than we are actually rendering them in the right place.)
- We don’t properly normalize string quotes. (At present, we just repeat any constants verbatim.)
- We’re mishandling a bunch of wrapping cases (if we treat Black as the reference implementation). Here are a few examples (demonstrating Black's stable behavior):

```py
# In some cases, if the end expression is "self-closing" (functions,
# lists, dictionaries, sets, subscript accesses, and any length-two
# boolean operations that end in these elments), Black
# will wrap like this...
if some_expression and f(
    b,
    c,
    d,
):
    pass

# ...whereas we do this:
if (
    some_expression
    and f(
        b,
        c,
        d,
    )
):
    pass

# If function arguments can fit on a single line, then Black will
# format them like this, rather than exploding them vertically.
if f(
    a, b, c, d, e, f, g, ...
):
    pass
```

- We don’t properly preserve parentheses in all cases. Black preserves parentheses in some but not all cases.
2023-02-15 04:06:35 +00:00
Charlie Marsh
f661c90bd7 Remove dependency on ruff_rowan (#2875)
This PR removes the dependency on `ruff_rowan` (i.e., Rome's fork of rust-analyzer's `rowan`), and in turn, trims out a lot of code in `ruff_formatter` that isn't necessary (or isn't _yet_ necessary) to power the autoformatter.

We may end up pulling some of this back in -- TBD. For example, the autoformatter has its own comment representation right now, but we may eventually want to use the `comments.rs` data structures defined in `rome_formatter`.
2023-02-15 03:54:08 +00:00
Charlie Marsh
5a84df293f Allow printing of consecutive empty lines (#2874) 2023-02-14 22:35:02 -05:00
Charlie Marsh
23d9309111 Remove JetBrains webinar badge (#2910) 2023-02-15 03:28:12 +00:00
Charlie Marsh
98ea94fdb7 Add StaticTextSlice kind to FormatElement enum (#2873)
Given our current parser abstractions, we need the ability to tell `ruff_formatter` to print a pre-defined slice from a fixed string of source code, which we've introduced here as `FormatElement::StaticTextSlice`.
2023-02-14 22:27:52 -05:00
Charlie Marsh
746e1d3436 Add contributors to acknowledgements (#2909) 2023-02-15 03:15:38 +00:00
Charlie Marsh
016ff01a04 Add an FAQ question around Python version support (#2908) 2023-02-15 03:11:44 +00:00
Charlie Marsh
298498e934 Add an Acknowledgements section to the README (#2907) 2023-02-15 00:25:07 +00:00
Charlie Marsh
3ef1c2e303 Add rome_formatter fork as ruff_formatter (#2872)
The Ruff autoformatter is going to be based on an intermediate representation (IR) formatted via [Wadler's algorithm](https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf). This is architecturally similar to [Rome](https://github.com/rome/tools), Prettier, [Skip](https://github.com/skiplang/skip/blob/master/src/tools/printer/printer.sk), and others.

This PR adds a fork of the `rome_formatter` crate from [Rome](https://github.com/rome/tools), renamed here to `ruff_formatter`, which provides generic definitions for a formatter IR as well as a generic IR printer. (We've also pulled in `rome_rowan`, `rome_text_size`, and `rome_text_edit`, though some of these will be removed in future PRs.)

Why fork? `rome_formatter` contains code that's specific to Rome's AST representation (e.g., it relies on a fork of rust-analyzer's `rowan`), and we'll likely want to support different abstractions and formatting capabilities (there are already a few changes coming in future PRs). Once we've dropped `ruff_rowan` and trimmed down `ruff_formatter` to the code we currently need, it's also not a huge surface area to maintain and update.
2023-02-14 19:22:55 -05:00
Simon Brugman
ac028cd9f8 [numpy] deprecated type aliases (#2810)
Closes https://github.com/charliermarsh/ruff/issues/2455

Used `NPY` as prefix code as agreed in the issue.
2023-02-14 23:45:12 +00:00
Edgar R. M
c0eb5c28d1 [docs] Add docs for flake8-errmsg (#2888) 2023-02-14 23:21:34 +00:00
Martin Fischer
a77b4566e4 Fix option links in mkdocs rule pages
In 28c9263722 I introduced automatic
linkification of option references in rule documentation,
which automatically converted the following:

    ## Options

    * `namespace-packages`

to:

    ## Options

    * [`namespace-packages`]

    [`namespace-packages`]: ../../settings#namespace-packages

While the above is a correct CommonMark[1] link definition,
what I was missing was that we used mkdocs for our documentation
generation, which as it turns out uses a non-CommonMark-compliant
Markdown parser, namely Python-Markdown, which contrary to CommonMark
doesn't support link definitions containing code tags.

This commit fixes the broken links via a regex hack.

[1]: https://commonmark.org/
2023-02-14 17:56:21 -05:00
Martin Fischer
860993187e Fix link relativization in generate_mkdocs.py 2023-02-14 17:56:21 -05:00
Charlie Marsh
58d4e00604 Add publish = false to unpublished crates (#2905) 2023-02-14 22:41:14 +00:00
Simon Legner
2d95912699 docs: fix ruff generate-shell-completion (#2904) 2023-02-14 22:38:29 +00:00
Simon Brugman
4f927fbacc [flake8-tidy-imports] autofix relative imports (#2891)
Previous fix was bugged. This one is only fixing when the `module_path` is present, making it far more robust.

Closes #2764 and closes #2869
2023-02-14 22:24:59 +00:00
Anders Kaseorg
2e41301520 Switch some quotes to backticks in errors (#2889)
Improves consistency with the style decision in #723, I think.
2023-02-14 22:24:41 +00:00
Martin Fischer
3179fc110d Disable many-to-one mapping for now 2023-02-14 16:16:12 -05:00
Martin Fischer
03ae0118b7 many-to-one 9/9: Update table generation 2023-02-14 16:16:12 -05:00
Martin Fischer
05176890ee many-to-one 8/9: Drop codes from registry
This commit was generated by running:

    fastmod --accept-all '[A-Z]+[0-9]+ => ' '' crates/ruff/src/registry.rs
2023-02-14 16:16:12 -05:00
Martin Fischer
849b947b3e many-to-one 7/9: Update JSON schema 2023-02-14 16:16:12 -05:00
Martin Fischer
c314e10e54 many-to-one 6/9: Implement ruff_macros::map_codes 2023-02-14 16:16:12 -05:00
Martin Fischer
9eda286dcd many-to-one 5/9: Generate codes.rs from registry.rs
# This commit was generated by running the following Python code:
# (followed by `sed -Ei 's/(mod registry;)/\1mod codes;/' crates/ruff/src/lib.rs`
# and `cargo fmt`).

import json
import re
import subprocess

def parse_registry():
    file = open('crates/ruff/src/registry.rs')

    rules = []

    while next(file) != 'ruff_macros::register_rules!(\n':
        continue

    while (line := next(file)) != ');\n':
        line = line.strip().rstrip(',')
        if line.startswith('//') or line.startswith('#['):
            rules.append(line)
            continue
        code, path = line.split(' => ')
        name = path.rsplit('::')[-1]
        rules.append((code, name))

    while (line := next(file)) != 'pub enum Linter {\n':
        continue

    prefixes = []
    prefix2linter = []

    while (line := next(file).strip()) != '}':
        if line.startswith('//'):
            continue
        if line.startswith('#[prefix = '):
            prefixes.append(line.split()[-1].strip('"]'))
        else:
            for prefix in prefixes:
                prefix2linter.append((prefix, line.rstrip(',')))
            prefixes.clear()

    prefix2linter.sort(key = lambda t: len(t[0]), reverse=True)

    return rules, prefix2linter

rules, prefix2linter = parse_registry()

def parse_code(code):
    prefix = re.match('[A-Z]+', code).group()
    if prefix in ('E', 'W'):
        return 'Pycodestyle', code

    for prefix, linter in prefix2linter:
        if code.startswith(prefix):
            return linter, code[len(prefix) :]

    assert False

text = '''
use crate::registry::{Linter, Rule};

pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
    #[allow(clippy::enum_glob_use)]
    use Linter::*;

    Some(match (linter, code) {
'''

for entry in rules:
    if isinstance(entry, str):
        if entry.startswith('//'):
            text += '\n' + entry
        else:
            text += entry
    else:
        namespace, code = parse_code(entry[0])
        text += f'({namespace}, "{code}") => Rule::{entry[1]},'
    text += '\n'

text += '''
       _ => return  None,
    })
}
'''

with open('crates/ruff/src/codes.rs', 'w') as f:
    f.write(text)
2023-02-14 16:16:12 -05:00
Martin Fischer
65a3461519 many-to-one 4/9: Rename define_rule_mapping! to register_rules!
Currently the define_rule_mapping! macro generates both the Rule enum as
well as the RuleCodePrefix enum and the mapping between the two.  After
this commit series the macro will only generate the Rule enum and the
RuleCodePrefix enum and the mapping will be generated by a new map_codes
proc macro, so we rename the macro now to fit its new purpose.
2023-02-14 16:16:12 -05:00
Martin Fischer
1b8d2df3bf many-to-one 3/9: Update RuleSelector::short_code
Same reasoning as for the previous commit ... one &'static str
becomes two &'static str because we split the RuleCodePrefix enum.
Note that the .unwrap() we have to add now, will actually
be removed in the 6th commit.
2023-02-14 16:16:12 -05:00
Martin Fischer
179ead0157 many-to-one 2/9: Newtype Rule::noqa_code return type
Rule::noqa_code previously return a single &'static str,
which was possible because we had one enum listing all
rule code prefixes. This commit series will however split up
the RuleCodePrefix enum into several enums ... so we'll end up
with two &'static str ... this commit wraps the return type
of Rule::noqa_code into a newtype so that we can easily change
it to return two &'static str in the 6th commit of this series.
2023-02-14 16:16:12 -05:00
Martin Fischer
d451c7a506 many-to-one 1/9: Rename Rule::code to Rule::noqa_code
Post this commit series several codes can be mapped to a single rule,
this commit therefore renames Rule::code to Rule::noqa_code,
which is the code that --add-noqa will add to ignore a rule.
2023-02-14 16:16:12 -05:00
Martin Fischer
502ce80c91 many-to-one 0/9: Introduce RuleSelector::Linter variant
We want to remove the variants denoting whole Linters
from the RuleCodePrefix enum, so we have to introduce
a new RuleSelector::Linter variant.
2023-02-14 16:16:12 -05:00
Charlie Marsh
49d22d8fe2 Ignore non-imperative-mood in Google docstring convention (#2900) 2023-02-14 20:42:20 +00:00
Chris May
08e0b76587 Add headers to configutation options (#2896)
This completes the word from the discussion in #2643, adding headers to clarify the `pyproject.toml` and `ruff.toml` sections.
2023-02-14 13:45:59 -05:00
Charlie Marsh
f7515739ac Improve consistency of some rule docs (#2887) 2023-02-14 04:36:37 +00:00
Sawbez
53e810ed3e [docs] Add docs for the entirety of flake8-builtins (#2840) 2023-02-14 04:30:30 +00:00
Charlie Marsh
66a195f805 Extend B904 to else branches (#2886) 2023-02-14 03:58:15 +00:00
Jeremiah England
b8483975a4 docs(SIM114): fix typo in example Python code (#2884) 2023-02-14 03:23:19 +00:00
Charlie Marsh
4dd2032687 Unversion unpublished crates (#2882) 2023-02-14 03:03:49 +00:00
Charlie Marsh
c6c15d5cf9 Avoid unnecessary-else violations in elif branches (#2881)
Long-time source of confusion -- two reports over 1800 issues apart.

Closes #1035.

Closes #2879.
2023-02-14 02:51:12 +00:00
Charlie Marsh
2bf7b35268 Re-enable custom allocators (#2876) 2023-02-14 02:37:22 +00:00
Charlie Marsh
6d1adc85fc Remove autofix for prefer-type-error (#2880) 2023-02-14 02:26:22 +00:00
Martin Fischer
02285c18d1 Remove autogenerated docs/rules/*.md files 2023-02-13 19:34:06 -05:00
Martin Fischer
8120d7c974 Change rule page links in README from GitHub to beta.ruff.rs 2023-02-13 19:34:06 -05:00
Martin Fischer
c858804ed4 refactor: Move docs/ gitignores to docs/.gitignore 2023-02-13 19:34:06 -05:00
Anders Kaseorg
b9d075c252 Alphabetize flake8-raise and flake8-self in documentation (#2871) 2023-02-13 18:03:09 -05:00
Charlie Marsh
7627e840c9 Avoid noqa removal upon unhandled syntax errors (#2864) 2023-02-13 10:37:55 -05:00
Charlie Marsh
3c03e2cb2e Rename flake8-django rules to match convention (#2861) 2023-02-13 15:30:04 +00:00
Charlie Marsh
aeae63b7ea Avoid false-positives for runtime-types in type checking blocks (#2863) 2023-02-13 10:26:34 -05:00
Charlie Marsh
7be17c5f1e Avoid false-positives with multi-byte characters in B005 (#2862) 2023-02-13 15:07:55 +00:00
Charlie Marsh
6128346b08 Re-show --target-version on CLI interface (#2859) 2023-02-13 15:04:11 +00:00
Charlie Marsh
1705574e75 Handle multiple receiver decorators in receiver-decorator (#2858) 2023-02-13 14:57:11 +00:00
Charlie Marsh
15f65fa8d6 Run cargo dev generate-all (#2860) 2023-02-13 14:55:44 +00:00
Ville Skyttä
d1cf0ee52b Remove "blanket" from RUF100 README message (#2844) 2023-02-13 14:43:35 +00:00
Florian Best
32520ff07f ci(gitignore): ignore VIM files (#2856) 2023-02-13 09:29:53 -05:00
Ville Skyttä
3659236580 Remove no longer needed setup.py INP001 ignore (#2846) 2023-02-13 09:00:35 -05:00
Charlie Marsh
dde69d50b5 Move more dependencies into workspace dependencies (#2842) 2023-02-13 04:19:26 +00:00
Charlie Marsh
67198ce7b3 Revert "Run release on tag creation"
This reverts commit c21a5912b9.
2023-02-12 23:11:31 -05:00
Charlie Marsh
c21a5912b9 Run release on tag creation 2023-02-12 22:33:01 -05:00
Charlie Marsh
48a5cd1dd9 Revert "perf: Use custom allocator (#2768)" (#2841)
This is causing wheel creation to fail on some of our more exotic build targets: https://github.com/charliermarsh/ruff/actions/runs/4159524132.

Let's figure out how to gate appropriately, but for now, reverting to get the release out.
2023-02-12 22:31:34 -05:00
Charlie Marsh
63f3d5e610 Update pre-commit instructions (#2838) 2023-02-13 00:06:40 +00:00
Charlie Marsh
7dab4807d0 Allow compound statements of single ellipsis (#2837)
This allows `class C: ...`-style compound statements in stub files.

Closes #2835.
2023-02-12 18:56:43 -05:00
Charlie Marsh
83f6e52c92 Bump version to 0.0.246 (#2834) 2023-02-12 23:39:51 +00:00
Charlie Marsh
5ce7ce5bc3 Check-in updated snapshot for SIM111 (#2836) 2023-02-12 23:37:52 +00:00
Florian Best
749d197119 docs(SIM114): fix typo in python code (#2833) 2023-02-12 18:35:29 -05:00
Charlie Marsh
46c184600f Include package inference during --add-noqa command (#2832) 2023-02-12 22:45:39 +00:00
Charlie Marsh
e2051ef72f Use smarter inversion for comparison checks (#2831) 2023-02-12 22:39:29 +00:00
Charlie Marsh
1abaece9ed Fix unused multi-assignments in a single pass (#2829) 2023-02-12 22:28:03 +00:00
Charlie Marsh
8b35b052b8 Avoid duplicates in if-with-same-arms (#2827) 2023-02-12 22:22:19 +00:00
Charlie Marsh
5a34504149 Implement ComparableStmt (#2826) 2023-02-12 22:00:01 +00:00
trag1c
0e53ddc2b3 Added Tables of Contents for CONTRIBUTING.md and CODE_OF_CONDUCT.md (#2824) 2023-02-12 16:38:18 -05:00
Colin Delahunty
1f07ad6e61 [flake8-simplify]: combine-if-conditions (#2823) 2023-02-12 21:00:32 +00:00
Charlie Marsh
1666e8ba1e Add a --show-fixes flag to include applied fixes in output (#2707) 2023-02-12 20:48:01 +00:00
Charlie Marsh
c399b3e6c1 Run cargo dev generate-all (#2822) 2023-02-12 19:11:49 +00:00
Charlie Marsh
9089ef74bc Upgrade RustPython (#2821) 2023-02-12 18:45:59 +00:00
Martin Fischer
28c9263722 Automatically linkify option references in rule documentation
Previously the rule documentation referenced configuration options
via full https:// URLs, which was bad for several reasons:

* changing the website would mean you'd have to change all URLs
* the links didn't work when building mkdocs locally
* the URLs showed up in the `ruff rule` output
* broken references weren't detected by our CI

This commit solves all of these problems by post-processing the
Markdown, recognizing sections such as:

    ## Options

    * `flake8-tidy-imports.ban-relative-imports`

`cargo dev generate-all` will automatically linkify such references
and panic if the referenced option doesn't exist.
Note that the option can also be linked in the other Markdown sections
via e.g. [`flake8-tidy-imports.ban-relative-imports`] since
the post-processing code generates a CommonMark link definition.

Resolves #2766.
2023-02-12 13:19:11 -05:00
Martin Fischer
fc4c927788 refactor: Introduce ConfigurationOptions::get method 2023-02-12 13:19:11 -05:00
Zeddicus414
26f39cac2f Add PD002 use-of-inplace-argument documentation (#2799) 2023-02-12 18:10:34 +00:00
Simon Brugman
02897a141b [flake8-tidy-imports] add documentation for banned-api (#2819) 2023-02-12 18:09:39 +00:00
Nyakku Shigure
fc465cc2af [flake8-pyi]: add rules for unrecognized platform check (PYI007, PYI008) (#2805)
Add two [flake8-pyi](https://github.com/PyCQA/flake8-pyi) rules (Y007, Y008). ref: #848

The specifications are described in [PEP 484 - Version and platform checking](https://peps.python.org/pep-0484/#version-and-platform-checking)

The original implementation in flake8-pyi is shown below.

- Implemention: 66f28a4407/pyi.py (L1429-L1443)
- Tests: 66f28a4407/tests/sysplatform.pyi
2023-02-12 18:02:38 +00:00
Charlie Marsh
ca8a122889 Add flake8-django to LICENSE (#2820) 2023-02-12 17:51:40 +00:00
Karol Onyśko
6769a5bce7 Implement flake8-django plugin rules (#2586) 2023-02-12 17:47:59 +00:00
Zeddicus414
fda93c6245 Add E722 bare-except documentation (#2796) 2023-02-12 16:51:32 +00:00
Charlie Marsh
099d5414f2 Allow non-verbose raise when cause is present (#2816)
The motivating issue here is of the following form:

```py
try:
    raise Exception("We want to hide this error message")
except Exception:
    try:
        raise Exception("We want to show this")
    except Exception as exc:
        raise exc from None
```

However, I think we should avoid this if _any_ cause is present, since causes require a named exception.

Closes #2814.
2023-02-12 16:48:13 +00:00
Charlie Marsh
9ddd5e4cfe Allow private accesses on super calls (#2815) 2023-02-12 16:11:25 +00:00
trag1c
b8835c2e35 Added MkDocs section to CONTRIBUTING.md (#2803) 2023-02-12 16:07:24 +00:00
Simon Brugman
1d4422f004 [flake8-comprehensions] improve autofix for C401, C402 and C417 (#2806) 2023-02-12 16:03:37 +00:00
Simon Brugman
2dccb7611a [flake8-comprehensions] bugfix for C413 autofix (#2804) 2023-02-12 15:56:07 +00:00
Simon Brugman
f8ac6d7bf0 fix: script add_plugin.py test import (#2807) 2023-02-12 09:58:23 -05:00
Simon Brugman
0123425be1 [flake8-comprehensions] autofix C414 and C417 + bugfix (#2693)
Closes https://github.com/charliermarsh/ruff/issues/2262 and closes https://github.com/charliermarsh/ruff/issues/2423

Fixes bug where some cases generated duplicated violations (see https://github.com/charliermarsh/ruff/pull/2732#issuecomment-1426397842)
2023-02-12 05:20:42 +00:00
Charlie Marsh
c53f91d943 Remove public re-export of commands (#2801) 2023-02-12 04:59:35 +00:00
Charlie Marsh
4a12ebb9b1 Improve f-string-missing-placeholders documentation (#2800) 2023-02-12 04:58:24 +00:00
Martin Fischer
0e4d5eeea7 Implement config subcommand
The synopsis is as follows.

List all top-level config keys:

    $ ruff config
    allowed-confusables
    builtins
    cache-dir
    ... etc.

List all config keys in a specific section:

    $ ruff config mccabe
    max-complexity

Describe a specific config option:

    $ ruff config mccabe.max-complexity
    The maximum McCabe complexity to allow before triggering `C901` errors.

    Default value: 10
    Type: int
    Example usage:
    ```toml
    # Flag errors (`C901`) whenever the complexity level exceeds 5.
    max-complexity = 5
    ```
2023-02-11 23:43:09 -05:00
Martin Fischer
bbe44360e8 refactor: Move name out of OptionField & OptionGroup 2023-02-11 23:43:09 -05:00
Martin Fischer
37e80d98ab refactor: Reorder members in ruff::settings::options_base 2023-02-11 23:43:09 -05:00
Charlie Marsh
306393063d Refactor generator to use Astor-derived precedence levels (#2798) 2023-02-12 04:30:16 +00:00
Martin Fischer
f5a3c90288 Rename new ruff rule output format to "pretty"
The new `ruff rule` output format introduced in
551b810aeb doesn't print Markdown but
rather some rich text with escape sequences for colors and links,
it's actually the "text" format that prints Markdown, so naming the new
format "markdown" is very confusing. This commit therefore renames it to
"pretty".

This isn't a breaking change since there hasn't been a release yet.
2023-02-11 23:23:37 -05:00
Charlie Marsh
8289ede00f Use output-stdout pattern for linter command (#2794) 2023-02-12 03:09:03 +00:00
Charlie Marsh
77e65c9ff5 Split commands.rs into separate files (#2792) 2023-02-12 02:58:13 +00:00
Charlie Marsh
d827a9156e Add documentation on enabling autocompletion (#2791) 2023-02-12 02:51:50 +00:00
Charlie Marsh
418808895e Add docs for f-string-missing-placeholders and unused-variable (#2790) 2023-02-12 02:48:36 +00:00
Charlie Marsh
ac4e212ed2 Move Wasm clippy to its own job (#2789) 2023-02-12 02:41:28 +00:00
Nick Pope
551b810aeb Add rendering of rule markdown for terminal output (#2747)
Add rendering of rule markdown for terminal output
    
This is achieved by making use of the `mdcat` crate.
    
See the following links for details:
    
- https://crates.io/crates/mdcat
- https://github.com/swsnr/mdcat
- https://docs.rs/mdcat/latest/mdcat/
2023-02-12 02:32:45 +00:00
Charlie Marsh
1b61d4e18b Support unused variable removal in multi-assignment statements (#2786) 2023-02-12 00:53:11 +00:00
Charlie Marsh
752c0150e1 Improve unused-variable autofixes for with statements (#2785) 2023-02-12 00:38:14 +00:00
Charlie Marsh
81651a8479 Respect continuations in noqa enforcement (#2783) 2023-02-11 23:29:37 +00:00
Charlie Marsh
86d0749ed7 Use consistent formatting for lint-failure messages (#2782) 2023-02-11 22:52:18 +00:00
Charlie Marsh
19fc410683 Remove raw string from hardcoded-sql-expression (#2780) 2023-02-11 20:05:57 +00:00
Charlie Marsh
5a70a573cd Avoid treating deferred string annotations as required-at-runtime (#2779) 2023-02-11 15:00:08 -05:00
Charlie Marsh
74731a3456 Fix reference to ban-relative-imports setting (#2776) 2023-02-11 18:34:25 +00:00
Micha Reiser
863e39fe5f perf: Use custom allocator (#2768)
This PR replaces the system allocator with a custom allocator to improve performance:

* Windows: mimalloc
* Unix: tikv-jemallocator

## Performance:

* Linux
  * `cpython --no-cache`: 208.8ms -> 190.5ms
  * `cpython`: 32.8ms -> 31ms
* Mac: 
  * `cpython --no-cache`: 436.3ms -> 380ms
  * `cpython`: 40.9ms -> 39.6ms
* Windows: 
  * `cpython --no-cache`: 367ms -> 268ms
  * `cpython`: 92.5ms -> 92.3ms
  
## Size

* Linux: +5MB from 13MB -> 18MB (I need to double check this)
* Mac: +0.7MB from 8.3MB-> 9MB
* Windows: -0.16MB from 8.29MB -> 8.13MB (that's unexpected)
2023-02-11 13:26:07 -05:00
Charlie Marsh
d0f9ee33ec Remove erroneous print statements 2023-02-11 12:45:40 -05:00
Charlie Marsh
1cf3d880a7 Don't treat all future import accesses as non-runtime (#2774)
This was just an oversight and misunderstanding on my part. We had some helpful tests, but I misunderstood the "right" behavior so thought they were passing.

Closes #2761.
2023-02-11 12:44:15 -05:00
Charlie Marsh
97dcb738fa Run cargo dev generate-all 2023-02-11 12:43:48 -05:00
Charlie Marsh
ffb4e89a98 Remove multiple-statements-on-one-line-def (E704) (#2773) 2023-02-11 12:34:21 -05:00
Charlie Marsh
43b7ee215c Ignore colon-after-lambda in compound statement rules (#2771) 2023-02-11 12:22:53 -05:00
Michał Mrówka
77099dcd4d implemented option lines-between-types for isort (#2762)
Fixes #2585

Add support for the isort option [lines_between_types](https://pycqa.github.io/isort/docs/configuration/options.html#lines-between-types)
2023-02-11 12:17:37 -05:00
Martin Fischer
70ff65154d Rename function-is-too-complex to complex-structure 2023-02-11 12:05:17 -05:00
Martin Fischer
7db6a2d6d4 Rename rules containing PEP reference in name 2023-02-11 12:05:17 -05:00
Martin Fischer
42924c0d9a Rename a bunch of pydocstyle rules 2023-02-11 12:05:17 -05:00
Martin Fischer
31d00936ee Drop no- from no-unnecessary-* rule names 2023-02-11 12:05:17 -05:00
Martin Fischer
c3c5d9a852 Rename nested-if-statements to collapsible-if 2023-02-11 12:05:17 -05:00
Martin Fischer
7e5c19385c Rename return-bool-condition-directly to needless-bool 2023-02-11 12:05:17 -05:00
Simon Brugman
5b54325c81 enable navigation in footer in docs (#2760) 2023-02-11 05:08:33 -05:00
trag1c
e6538a7969 Added logo and favicon for mkdocs (#2757) 2023-02-10 23:34:47 -05:00
Charlie Marsh
24faabf1f4 Bump version to 0.0.245 2023-02-10 22:15:27 -05:00
Charlie Marsh
9b0a160239 Only update docs on release (#2755) 2023-02-10 22:14:50 -05:00
Charlie Marsh
9fd29e2c54 Mention default in relative-imports doc 2023-02-10 22:12:22 -05:00
Simon Brugman
e83ed0ecba Implement autofix for relative imports (TID252) (#2739) 2023-02-10 22:05:47 -05:00
Charlie Marsh
dadbfea497 Flag private member accesses on calls et al (#2753) 2023-02-10 19:23:22 -05:00
Nick Pope
9f84c497f9 Adjust heading level in rule documentation (#2749) 2023-02-10 19:10:42 -05:00
Martin Fischer
0ec25d1514 Rename dynamically-typed-expression to any-type (#2751) 2023-02-10 19:02:31 -05:00
Charlie Marsh
6a87c99004 Use explicit fields for implicit-namespace-package 2023-02-10 18:09:30 -05:00
Charlie Marsh
c8f60c9588 Improve implicit-namespace-package documentation 2023-02-10 18:06:48 -05:00
Charlie Marsh
113610a8d4 Improve hardcoded-sql-expression documentation 2023-02-10 18:03:01 -05:00
Charlie Marsh
6376e5915e Improve dynamically-typed-expression documentation 2023-02-10 17:55:26 -05:00
Charlie Marsh
3d8fb5be20 Rewrite documentation for yield-in-init (#2748) 2023-02-10 17:49:55 -05:00
Charlie Marsh
0040991778 Respect NO_COLOR flags in --show-source (#2750) 2023-02-10 17:27:40 -05:00
Charlie Marsh
acb70520f8 Add colored environment variables to README (#2746) 2023-02-10 17:06:02 -05:00
Charlie Marsh
6eb9268675 Allow named unicodes in bidirectional escape check (#2710) 2023-02-10 16:59:28 -05:00
Charlie Marsh
e5f5142e3e Improve yield-in-init documentation 2023-02-10 16:47:44 -05:00
Charlie Marsh
98d5ffb817 Fix __init__.py-to-__init__ in documentation 2023-02-10 16:30:36 -05:00
Charlie Marsh
3f20f73413 Use function_type::classify for yield-in-init (#2742) 2023-02-10 16:19:45 -05:00
tomecki
a5e42d2f7c pylint: E0100 yield-in-init (#2716) 2023-02-10 16:15:15 -05:00
Charlie Marsh
0bc1f68111 Only trigger compound statements after select keywords (#2737) 2023-02-10 15:21:06 -05:00
Charlie Marsh
d2b09d77c5 Only validate __all__ bindings for global scope (#2738) 2023-02-10 15:16:21 -05:00
Charlie Marsh
0377834f9f Mark __all__ members as used at end-of-scope (#2733) 2023-02-10 14:32:05 -05:00
Charlie Marsh
3d650f9dd6 Relax conditions in bad-string-format-type (#2731) 2023-02-10 14:25:59 -05:00
Charlie Marsh
a72590ecde Expand S110 and S112 ranges to include entire exception handler (#2729) 2023-02-10 13:27:18 -05:00
Charlie Marsh
812b227334 Avoid flagging typed exceptions in tuples (#2728) 2023-02-10 13:24:45 -05:00
Martin Fischer
6f58717ba4 refactor: Stop including Rule::code() in pycodestyle .snap filenames 2023-02-10 13:15:47 -05:00
Florian Best
8aab96fb9e feat(isort): Implement known-local-folder (#2657) 2023-02-10 13:15:34 -05:00
Nick Pope
9e6f7153a9 Handle more functions that never return in RET503 (#2719) 2023-02-10 12:09:05 -05:00
Peter Pentchev
cda2ff0b18 Handle functions that never return in RET503 (#2701) 2023-02-10 09:28:34 -05:00
Martin Fischer
ec63658250 Disallow rule names starting with avoid-* 2023-02-10 09:25:29 -05:00
Martin Fischer
1a97de0b01 Disallow rule names starting with uses-* 2023-02-10 09:25:29 -05:00
Martin Fischer
1cbe48522e Disallow rule names ending in *-used 2023-02-10 09:25:29 -05:00
Martin Fischer
bfbde537af Disallow rule names starting with do-not-* 2023-02-10 09:25:29 -05:00
Martin Fischer
cba91b758b Add test for rule names 2023-02-10 09:25:29 -05:00
Martin Fischer
0bab642f5a Describe rule naming convention in CONTRIBUTING.md 2023-02-10 09:25:29 -05:00
Martin Fischer
bd09a1819f Drop unused once_cell dependency from ruff_macros 2023-02-10 09:25:29 -05:00
Martin Fischer
682d206992 refactor: Reduce code duplication 2023-02-10 08:24:22 -05:00
Martin Fischer
c32441e4ab refactor: Use format! keyword arguments 2023-02-10 08:24:22 -05:00
Martin Fischer
6f16f1c39b refactor: Reduce code duplication 2023-02-10 08:24:22 -05:00
Martin Fischer
9011456aa1 refactor: Simplify attribute handling in rule_code_prefix
if_all_same(codes.values().cloned()).unwrap_or_default()

was quite unreadable because it wasn't obvious that codes.values() are
the prefixes. It's better to introduce another Map rather than having
Maps within Maps.
2023-02-10 08:24:22 -05:00
Martin Fischer
fa191cceeb refactor: Avoid implicit precondition 2023-02-10 08:24:22 -05:00
Charlie Marsh
ac6c3affdd Remove public Rust API (#2709) 2023-02-09 23:16:49 -05:00
Charlie Marsh
9a018c1650 Import AutofixKind from violation 2023-02-09 23:06:02 -05:00
Charlie Marsh
0aef5c67a3 Remove src/registry.rs 2023-02-09 23:04:28 -05:00
Charlie Marsh
a048594416 Gate Path.readlink() behind Python 3.9+ guard (#2708) 2023-02-09 22:57:31 -05:00
Charlie Marsh
5437f1299b Remove lifetimes from Printer (#2704) 2023-02-09 21:44:15 -05:00
Charlie Marsh
41c0608a69 Add test module a test-only module (#2703) 2023-02-09 21:28:10 -05:00
messense
eb0d42187f Manage LibCST and RustPython with cargo workspace dependencies (#2700) 2023-02-09 20:49:50 -05:00
Colin Delahunty
48daa0f0ca [pylint]: bad-string-format-type (#2572) 2023-02-09 20:08:56 -05:00
Charlie Marsh
417fe4355f Add colors to statistics output (#2699) 2023-02-09 19:40:29 -05:00
Florian Best
a129181407 feat(cli): let --statistics show fixable codes (#2659) 2023-02-09 19:36:31 -05:00
Matt Oberle
fc628de667 Implement bandit's 'hardcoded-sql-expressions' S608 (#2698)
This is an attempt to implement `bandit` rule `B608` (renamed here `S608`).
- https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html

The rule inspects strings constructed via `+`, `%`, `.format`, and `f""`.

- `+` and `%` via `BinOp`
- `.format` via `Call`
- `f""` via `JoinedString`

Any SQL-ish strings that use Python string formatting are flagged.

The expressions and targeted expression types for the rule come from here:
- 7104b336d3/bandit/plugins/injection_sql.py

> Related Issue: https://github.com/charliermarsh/ruff/issues/1646
2023-02-09 19:28:17 -05:00
Charlie Marsh
9e2418097c Run cargo dev generate-all 2023-02-09 19:14:02 -05:00
Charlie Marsh
d4e5639aaf Add flake8-pyi to CONTRIBUTING.md 2023-02-09 19:04:55 -05:00
Steve Dignam
67e58a024a Add flake8-pyi with one rule (#2682)
Add basic scaffold for [flake8-pyi](https://github.com/PyCQA/flake8-pyi) and the first rule, Y001

rel: https://github.com/charliermarsh/ruff/issues/848
2023-02-09 19:03:11 -05:00
Charlie Marsh
233be0e074 Suppress parse errors with explicit # noqa: E999 directives (#2697) 2023-02-09 18:24:19 -05:00
Nick Pope
7750087f56 Remove duplicate documentation for TRY002 (#2692) 2023-02-09 12:08:00 -05:00
Charlie Marsh
7d5fb0de8a Add documentation for mccabe, isort, and flake8-annotations (#2691) 2023-02-09 11:56:18 -05:00
Charlie Marsh
8a98cfc4b8 Treat re-exported annotations as used-at-runtime (#2689) 2023-02-09 11:22:15 -05:00
Charlie Marsh
54d1719424 Hide rule configuration settings on CLI (#2687) 2023-02-09 11:13:04 -05:00
Charlie Marsh
0f622f0126 Upgrade RustPython to pull in newline-handling optimizations (#2688) 2023-02-09 11:12:43 -05:00
Charlie Marsh
739a92e99d Implement compound-statements (E701, E702, E703, E704) (#2680) 2023-02-08 22:57:39 -05:00
Charlie Marsh
5a07c9f57c Only include rule links once in README (#2678) 2023-02-08 21:48:05 -05:00
Colin Delahunty
31027497c6 [flake8-bandit]: try-except-continue (#2674) 2023-02-08 21:44:01 -05:00
Charlie Marsh
dabfdf718e Mark flake8-simplify rules as unfixable in non-fixable cases (#2676) 2023-02-08 21:28:28 -05:00
Charlie Marsh
5829bae976 Support callable decorators in classmethod_decorators et al (#2675) 2023-02-08 21:11:36 -05:00
Charlie Marsh
ff3665a24b Mark RUF005 as fixable 2023-02-08 18:02:33 -05:00
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
Charlie Marsh
651f6b6bce Bump Ruff version to 0.0.240 2023-02-02 12:45:23 -05:00
Charlie Marsh
d3c3198b24 Fix versions in BREAKING_CHANGES.md 2023-02-02 12:45:20 -05:00
Charlie Marsh
ec6054edce Treat if 0: and if False: as type-checking blocks (#2485) 2023-02-02 12:35:59 -05:00
Charlie Marsh
a0df78cb7d Visit NamedExpr values before targets (#2484) 2023-02-02 12:21:58 -05:00
Aarni Koskela
ac41c33d1f Move flake8-blind-except violation to rule module (#2479) 2023-02-02 12:21:25 -05:00
Aarni Koskela
b4b8782243 Move remaining flake8-pytest-style violations to rule modules (#2482) 2023-02-02 12:10:49 -05:00
Florian Best
8e53a4d1d3 fix: assertTrue()/assertFalse() fixer should not test for identity (#2476) 2023-02-02 11:24:35 -05:00
Charlie Marsh
668860cba3 Add more information to Pylint FAQ section 2023-02-02 11:08:17 -05:00
Aarni Koskela
038e8cfba0 Move flake8-quotes violations to rules module (#2475) 2023-02-02 10:08:12 -05:00
Aarni Koskela
ebfa55cea3 Move flake8-builtins violations to rules file (#2478) 2023-02-02 10:03:09 -05:00
Aarni Koskela
aa0fc0f9c2 Move flake8-bugbear violations to rule modules (#2474) 2023-02-02 09:34:26 -05:00
Aarni Koskela
aa85c81280 Move flake8-comprehensions violations to rule files (#2477) 2023-02-02 09:26:50 -05:00
Charlie Marsh
f5fd6f59ea Remove extraneous test file 2023-02-02 08:46:03 -05:00
Martin Fischer
540e31f5f4 Carry-over ignore to next config layer if select = [] (#2467)
Resolves #2461.
2023-02-02 08:45:07 -05:00
Chris Chan
8136cc9238 Implement pylint's too-many-statements rule (PLR0915) (#2445) 2023-02-02 08:18:37 -05:00
Charlie Marsh
2c71535016 Update snapshots 2023-02-02 08:15:33 -05:00
Aarni Koskela
cce8fb9882 isort: support forced_separate (#2268) 2023-02-02 08:08:02 -05:00
Maksudul Haque
9e59c99133 [flake8-self] Add Plugin and Rule SLF001 (#2470) 2023-02-02 07:58:14 -05:00
Colin Delahunty
b032f50775 [pyupgrade]: Remove outdated sys.version_info blocks (#2099) 2023-02-02 07:49:24 -05:00
Charlie Marsh
1c2fc38853 Use LibCST to reverse Yoda conditions (#2468)
Our existing solution was having trouble with parenthesized expressions. This actually may affect more than `SIM300`, but let's address them as they come up.

Closes #2466.
2023-02-02 00:07:43 -05:00
Charlie Marsh
f16f3a4a03 Avoid removing un-selected codes when applying --add-noqa edits (#2465)
The downside here is that we have to leave blank `# noqa` directives intact. Otherwise, we risk removing necessary `# noqa` coverage for rules that aren't selected.

Closes #2254.
2023-02-01 22:22:31 -05:00
Charlie Marsh
30a09ec211 Respect parent noqa in --add-noqa (#2464) 2023-02-01 21:58:01 -05:00
Reid Swan
ec7b25290b feat: Add isort option lines-after-imports (#2440)
Fixes https://github.com/charliermarsh/ruff/issues/2243

Adds support for the isort option [lines_after_imports](https://pycqa.github.io/isort/docs/configuration/options.html#lines-after-imports) to insert blank lines between imports and the follow up code.
2023-02-01 21:39:45 -05:00
Charlie Marsh
68422d4ff2 Allow non-ruff.toml-named files for --config (#2463)
Previously, if you passed in a file on the command-line via `--config`, it had to be named either `pyproject.toml` or `ruff.toml` -- otherwise, we errored. I think this is too strict. `pyproject.toml` is a special name in the ecosystem, so we should require _that_; but otherwise, let's just assume it's in `ruff.toml` format.

As an alternative, we could add a `--pyproject` argument for `pyproject.toml`, and assume anything passed to `--config` is in `ruff.toml` format. But that _would_ be a breaking change and is arguably more confusing. (This isn't a breaking change, since it only loosens the CLI.)

Closes #2462.
2023-02-01 21:35:42 -05:00
Charlie Marsh
2abaffd65b Improve consistency of backticks for plugin names (#2460) 2023-02-01 19:17:32 -05:00
Charlie Marsh
06cbf5a2ae Add some top-level links to the README (#2458) 2023-02-01 19:10:41 -05:00
Charlie Marsh
f432ce291a Add Fathom to docs 2023-02-01 18:41:24 -05:00
Charlie Marsh
1eb331143d Add Fathom to playground 2023-02-01 18:30:40 -05:00
Henry Schreiner
db1b1672b8 fix: minor spacing typo in message for PTH123 (#2453) 2023-02-01 14:39:50 -05:00
Charlie Marsh
6861e59103 Only avoid PEP604 rewrites for pre-Python 3.10 code (#2449)
I moved the `self.in_annotation` guard out of the version check in #1563. But, I think that was a mistake. It was done to resolve #1560, but the fix in that case _should've_ been to set a different Python version.

Closes #2447.
2023-02-01 13:03:51 -05:00
Charlie Marsh
778c644ee3 Trigger, but don't fix, SIM rules if comments are present (#2450) 2023-02-01 12:56:02 -05:00
Martin Fischer
e66a6b6d05 refactor: Define ruff_dev::ROOT_DIR 2023-02-01 09:17:53 -05:00
Martin Fischer
faea478ca5 fix: failing snapshot test on Windows 2023-02-01 09:17:53 -05:00
Martin Fischer
39b5fa0e24 refactor: Make test_path prefix the fixture path 2023-02-01 09:17:53 -05:00
Martin Fischer
df413d1ece refactor: Introduce test_resource_path helper 2023-02-01 09:17:53 -05:00
Martin Fischer
cfd0693ae5 refactor: Document internal test_path function 2023-02-01 09:17:53 -05:00
Martin Fischer
56ad160c05 refactor: Move test_path helper to new test module 2023-02-01 09:17:53 -05:00
Florian Best
9d8c6ba671 more builtin name checks when autofixing (#2430) 2023-02-01 08:16:47 -05:00
Charlie Marsh
1ea88ea56b Avoid iterating over body twice (#2439) 2023-02-01 08:12:36 -05:00
Florian Best
7f44ffb55c docs(CONTRIBUTING): add instructions how to update the test snapshots (#2412) 2023-02-01 07:44:20 -05:00
Charlie Marsh
dbd640d90f Remove unused Cargo.lock file (#2437) 2023-02-01 07:33:59 -05:00
Aarni Koskela
e5082c7d6c isort: split up package (#2434) 2023-02-01 07:17:31 -05:00
Charlie Marsh
841d176289 Move super-args and unnecessary-coding-comment into their own modules (#2432) 2023-01-31 22:26:56 -05:00
Charlie Marsh
c15595325c Bump version to 0.0.239 2023-01-31 19:06:22 -05:00
Florian Best
e97b1a4280 fix: ignore fix if "bool" is not builtin (#2429) 2023-01-31 19:03:46 -05:00
Florian Best
82ec884a61 feat: let SIM210 return expressions without bool() wrapping (#2410) (#2426) 2023-01-31 18:25:22 -05:00
Maksudul Haque
7c1a6bce7b [flake8-raise] Add Plugin and RSE102 Rule (#2354) 2023-01-31 18:09:40 -05:00
Charlie Marsh
84a8b628b8 Avoid implicit-namespace-package checks for .pyi files (#2420) 2023-01-31 17:35:30 -05:00
Charlie Marsh
142b627bb8 Avoid Bandit false-positives for empty-string-as-password (#2421) 2023-01-31 16:56:03 -05:00
Charlie Marsh
fbf231e1b8 Allow implicit multiline strings with internal quotes to use non-preferred quote (#2416)
As an example, if you have `single` as your preferred style, we'll now allow this:

```py
assert s.to_python(123) == (
    "123 info=SerializationInfo(include=None, exclude=None, mode='python', by_alias=True, exclude_unset=False, "
    "exclude_defaults=False, exclude_none=False, round_trip=False)"
)
```

Previously, the second line of the implicit string concatenation would be flagged as invalid, despite the _first_ line requiring double quotes. (Note that we'll accept either single or double quotes for that second line.)

Mechanically, this required that we process sequences of `Tok::String` rather than a single `Tok::String` at a time. Prior to iterating over the strings in the sequence, we check if any of them require the non-preferred quote style; if so, we let _any_ of them use it.

Closes #2400.
2023-01-31 16:27:15 -05:00
Florian Best
1dd9ccf7f6 feat: let SIM103 return expressions without bool() wrapping (#2410) 2023-01-31 16:11:44 -05:00
Charlie Marsh
d601abe01b Rename flake8-quotes snapshots and tests (#2415) 2023-01-31 16:08:00 -05:00
Charlie Marsh
15d4774b6b Avoid flagging same-condition cases in SIM103 (#2404) 2023-01-31 12:45:51 -05:00
Charlie Marsh
293c7e00d5 Include method name in B027 message (#2403) 2023-01-31 12:41:22 -05:00
Thomas M Kehrenberg
c3a3195922 Fix option name "max-args" in the documentation (#2401) 2023-01-31 12:30:05 -05:00
Martin Fischer
39d98d3488 Disable panic hook about reporting issues for debug builds
In order to avoid confusing new developers.  When a debug build panics
chances are that the panic is caused by local changes and should in
fact not be reported on GitHub.
2023-01-31 12:24:26 -05:00
Charlie Marsh
cd3d82213a Handle multi-byte lines in RUF100 (#2392) 2023-01-31 07:59:16 -05:00
Charlie Marsh
a9a0026f2f Don't panic for --statistics with no errors (#2391) 2023-01-31 07:53:29 -05:00
Hassan Kibirige
da4618d77b For neovim:null_ls use ruff builtin for formatting (#2386)
null_ls picked up the recommended snippet in README.md and ruff formatting now a builtin.

Ref:
1. 482990e391

2. 7b2b28e207/doc/BUILTINS.md (ruff-1)
2023-01-31 07:22:14 -05:00
Martin Fischer
1b0748d19d refactor: Simplify Linter::categories 2023-01-31 07:21:12 -05:00
Martin Fischer
0b7fa64481 refactor: Drop PartialOrd & Ord impls for RuleSelector
RuleSelector implemented PartialOrd & Ord because ruff::flake8_to_ruff
was using RuleSelector within a BTreeSet (which requires contained
elements to implement Ord). There however is no inherent order to
rule selectors, so PartialOrd & Ord should not be implemented.

This commit changes BTreeSet<RuleSelector> to HashSet<RuleSelector>
and adds an explicit sort calls based on the serialized strings,
letting us drop the PartialOrd & Ord impls in favor of a Hash impl.
2023-01-31 07:21:12 -05:00
Samuel Cormier-Iijima
09d593b124 [I001] fix isort check for files with tabs and no indented blocks (#2374)
This is a followup to #2361. The isort check still had an issue in a rather specific case: files with a multiline import, indented with tabs, and not containing any indented blocks.

The root cause is this: [`Stylist`'s indentation detection](ad8693e3de/src/source_code/stylist.rs (L163-L172)) works by finding `Indent` tokens to determine the type of indentation used by a file. This works for indented code blocks (loops/classes/functions/etc) but does not work for multiline values, so falls back to 4 spaces if the file doesn't contain code blocks.

I considered a few possible solutions:

1. Fix `detect_indentation` to avoid tokenizing and instead use some other heuristic to determine indentation. This would have the benefit of working in other places where this is potentially an issue, but would still fail if the file doesn't contain any indentation at all, and would need to fall back to option 2 anyways.
2. Add an option for specifying the default indentation in Ruff's config. I think this would confusing, since it wouldn't affect the detection behavior and only operate as a fallback, has no other current application and would probably end up being overloaded for other things.
3. Relax the isort check by comparing the expected and actual code's lexed tokens. This would require an additional lexing step.
4. Relax the isort check by comparing the expected and actual code modulo whitespace at the start of lines.

This PR does approach 4, which in addition to being the simplest option, has the (expected, although I didn't benchmark) added benefit of improved performance, since the check no longer needs to do two allocations for the two `dedent` calls. I also believe that the check is still correct enough for all practical purposes.
2023-01-31 07:18:54 -05:00
Erik Welch
adc134ced0 Fix typos: s/scripy/scipy/g (#2380) 2023-01-31 07:17:18 -05:00
Charlie Marsh
6051a0c1c8 Include per-file ignore matches in debug logging (#2376) 2023-01-30 23:11:56 -05:00
Charlie Marsh
00495e8620 Use human-readable types for documentation values (#2375) 2023-01-30 23:05:28 -05:00
Colin Delahunty
ad8693e3de [pyupgrade] Implement import-replacement rule (UP035) (#2049) 2023-01-30 19:58:28 -05:00
Charlie Marsh
69e20c4554 Minor improvements to the docs (#2371) 2023-01-30 19:06:05 -05:00
Charlie Marsh
b5816634b3 Add a link to MkDocs (#2370) 2023-01-30 19:00:57 -05:00
Charlie Marsh
e8810eae64 Fix version number in BREAKING_CHANGES.md 2023-01-30 18:49:11 -05:00
Charlie Marsh
ba26a60e2a Disable incompatible rules rather than merely warning (#2369)
This is another temporary fix for the problem described in #2289 and #2292. Rather than merely warning, we now disable the incompatible rules (in addition to the warning). I actually think this is quite a reasonable solution, but we can revisit later. I just can't bring myself to ship another release with autofix broken-by-default 😂
2023-01-30 18:47:05 -05:00
Charlie Marsh
42459c35b0 Update BREAKING_CHANGES.md 2023-01-30 17:50:26 -05:00
Charlie Marsh
1cbd929a0a Bump version to 0.0.238 2023-01-30 16:44:19 -05:00
Charlie Marsh
5f07e70762 Recommend disabling explicit-string-concatenation (#2366)
If `allow-multiline = false` is set, then if the user enables `explicit-string-concatenation` (`ISC003`), there's no way for them to create valid multiline strings. This PR notes that they should turn off `ISC003`.

Closes #2362.
2023-01-30 16:42:30 -05:00
Charlie Marsh
8963a62ec0 Refine criteria for exc_info logger rules (#2364)
We now only trigger `logging-exc-info` and `logging-redundant-exc-info` when in an exception handler, with an `exc_info` that isn't `true` or `sys.exc_info()`.

Closes #2356.
2023-01-30 16:32:00 -05:00
Charlie Marsh
4589daa0bd Ignore magic comparisons to bytes by default (#2365) 2023-01-30 16:31:48 -05:00
Charlie Marsh
ea0274d22c Use bold for deprecated 2023-01-30 16:28:21 -05:00
Charlie Marsh
ca1129ad27 Document new rule config resolution 2023-01-30 16:26:59 -05:00
Martin Fischer
104c63afc6 Exclude deprecated extend-ignore from the JSON schema
Now that the option is deprecated we no longer
want IDEs to suggest it in their autocompletion.
2023-01-30 16:26:59 -05:00
Martin Fischer
ba457c21b5 Improve rule config resolution
Ruff allows rules to be enabled with `select` and disabled with
`ignore`, where the more specific rule selector takes precedence,
for example:

    `--select ALL --ignore E501` selects all rules except E501
    `--ignore ALL --select E501` selects only E501

(If both selectors have the same specificity ignore selectors
take precedence.)

Ruff always had two quirks:

* If `pyproject.toml` specified `ignore = ["E501"]` then you could
  previously not override that with `--select E501` on the command-line
  (since the resolution didn't take into account that the select was
  specified after the ignore).

* If `pyproject.toml` specified `select = ["E501"]` then you could
  previously not override that with `--ignore E` on the command-line
  (since the resolution didn't take into account that the ignore was
  specified after the select).

Since d067efe265 (#1245)
`extend-select` and `extend-ignore` always override
`select` and `ignore` and are applied iteratively in pairs,
which introduced another quirk:

* If some `pyproject.toml` file specified `extend-select`
  or `extend-ignore`, `select` and `ignore` became pretty much
  unreliable after that with no way of resetting that.

This commit fixes all of these quirks by making later configuration
sources take precedence over earlier configuration sources.

While this is a breaking change, we expect most ruff configuration
files to not rely on the previous unintutive behavior.
2023-01-30 16:26:59 -05:00
Martin Fischer
a92958f941 Test that more specific select wins over less specific ignore 2023-01-30 16:26:59 -05:00
Martin Fischer
1cd206285e refactor: test impl From<&Configuration> for RuleTable
Previously we tested the resolve_codes helper function directly.
Since we want to rewrite our resolution logic in the next commit,
this commit changes the tests to test the more high-level From impl.
2023-01-30 16:26:59 -05:00
Samuel Cormier-Iijima
5ac5b69e9f [I001] fix isort for files with tab-based indentation (#2361)
This PR fixes two related issues with using isort on files using tabs for indentation:

- Multiline imports are never considered correctly formatted, since the comparison with the generated code will always fail.
- Using autofix generates code that can have mixed indentation in the same line, for imports that are within nested blocks.
2023-01-30 15:36:19 -05:00
Charlie Marsh
01fedec1e7 Add SciPy and meson-python (#2363) 2023-01-30 15:34:19 -05:00
Martin Fischer
ef20692149 fix: clap usage for CLI help generation in the README (#2358) 2023-01-30 13:14:40 -05:00
Simon Brugman
50046fbed3 Extend conventional imports defaults to include TensorFlow et al (#2353)
extend conventional imports

Based on configuration from Visual Studio for Python
(https://code.visualstudio.com/docs/python/editing#_quick-fixes)
2023-01-30 11:04:19 -05:00
Charlie Marsh
6798675db1 Avoid removing trailing comments when autofixing (#2352) 2023-01-30 07:44:20 -05:00
Akhil
8e5a944ce1 Implement Pylint's too-many-arguments rule (PLR0913) (#2308) 2023-01-30 07:34:37 -05:00
messense
1e325edfb1 Configure automatically generated release notes (#2341) 2023-01-30 07:21:29 -05:00
Simon Brugman
502574797f include tomllib in standard lib (#2345) 2023-01-30 06:59:59 -05:00
Charlie Marsh
7a83b65fbe Pre-allocate output contents during autofix application (#2340) 2023-01-29 22:40:27 -05:00
Charlie Marsh
74e3cdfd7c Add a dedicated single-fix helper (#2339) 2023-01-29 22:38:29 -05:00
Simon Brugman
2ef28f217c pandas vet autofix for PD002 and general refactor 2023-01-29 22:30:37 -05:00
Simon Brugman
63fc912ed8 refactor: use remove_argument helper in pyupgrade 2023-01-29 22:30:37 -05:00
Martin Fischer
d76a47d366 Implement ruff linter subcommand
The subcommand lists all supported upstream linters and their prefixes:

    $ ruff linter
       F Pyflakes
     E/W pycodestyle
     C90 mccabe
       I isort
       N pep8-naming
       D pydocstyle
      UP pyupgrade
     YTT flake8-2020
    # etc...

Just like with the `rule` subcommand `--format json` is supported:

    $ ruff linter --format json
    [
      {
        "prefix": "F",
        "name": "Pyflakes"
      },
      {
        "prefix": "",
        "name": "pycodestyle",
        "categories": [
          {
            "prefix": "E",
            "name": "Error"
          },
          {
            "prefix": "W",
            "name": "Warning"
          }
        ]
      },
      # etc...
2023-01-29 21:32:37 -05:00
Martin Fischer
b532fce792 refactor: Change RuleNamespace::prefixes to common_prefix
Previously Linter::parse_code("E401") returned
(Linter::Pycodestyle, "401") ... after this commit it returns
(Linter::Pycodestyle, "E401") instead, which is important
for the future implementation of the many-to-many mapping.
(The second value of the tuple isn't used currently.)
2023-01-29 21:32:37 -05:00
Charlie Marsh
3ee6a90905 Remove remove-six-compat (UP016) (#2332) 2023-01-29 21:19:59 -05:00
Samuel Cormier-Iijima
0a6d2294a7 [TRY201] don't check raise statements in nested exception handlers (#2337) 2023-01-29 21:16:18 -05:00
Simon Brugman
e66fb42d0b refactor: use patch(diagnostic.kind.rule()) (#2336) 2023-01-29 21:15:09 -05:00
Simon Brugman
5165b703d9 Add VS Code to gitignore; fix typos (#2333) 2023-01-29 21:14:38 -05:00
Simon Brugman
b40cd1fabc debug assert for fix usage (#2335) 2023-01-29 21:13:42 -05:00
Charlie Marsh
64fb0bd2cc Include both ruff help and ruff help check in README (#2325) 2023-01-29 17:01:15 -05:00
Charlie Marsh
2ad29089af Allow list comprehensions for __all__ assignment (#2326) 2023-01-29 14:26:54 -05:00
Florian Best
f41796d559 feat: add ruff --statistics (#2284)
Closes #2284.
2023-01-29 13:44:56 -05:00
Samuel Cormier-Iijima
945a9e187c Migrate violations to named fields (#2317)
Fairly mechanical. Did a few of the simple cases manually to make sure things were working, and I think the rest will be easily achievable via a quick `fastmod` command.

ref #1871
2023-01-29 13:29:53 -05:00
Charlie Marsh
546413defb Fix remaining RelativeImportsOrder typo 2023-01-29 11:33:12 -05:00
Charlie Marsh
e371ef9b1a Place star before other member imports (#2320)
I think we've never run into this case, since it's rare to import `*` from a module _and_ import some other member explicitly. But we were deviating from `isort` by placing the `*` after other members, rather than up-top.

Closes #2318.
2023-01-28 22:17:43 -05:00
Charlie Marsh
c9585fe304 Run generate-all 2023-01-28 22:13:07 -05:00
Charlie Marsh
535868f939 Update fixable list (#2316) 2023-01-28 20:18:55 -05:00
Chirag
cec993aaa9 Add ruff . to documentation (#2307) 2023-01-28 14:53:11 -05:00
Samuel Cormier-Iijima
1a32d873f0 Fix regression with line-based rules not being ignored per-file (#2311) 2023-01-28 14:48:32 -05:00
Samuel Cormier-Iijima
f308f9f27e Respect per-file-ignores when checking noqa (#2309)
`RUF100` does not take into account a rule ignored for a file via a `per-file-ignores` configuration. To see this, try the following pyproject.toml:

```toml
[tool.ruff.per-file-ignores]
"test.py" = ["F401"]
```

and this test.py file:

```python
import itertools  # noqa: F401
```

Running `ruff --extend-select RUF100 test.py`, we should expect to get this error:

```
test.py:1:19: RUF100 Unused `noqa` directive (unused: `F401`)
```

The issue is that the per-file-ignores diagnostics are filtered out after the noqa checks, rather than before.
2023-01-28 14:16:30 -05:00
Jonathan Plasse
73dccce5f5 Isolate integration tests (#2306) 2023-01-28 13:32:50 -05:00
Charlie Marsh
fc9fae6579 Remove picture tag from PyPI and MkDocs 2023-01-28 11:49:52 -05:00
Charlie Marsh
add7fefeb5 Bump version to 0.0.237 2023-01-28 10:52:14 -05:00
Charlie Marsh
ec24947865 Fix version shorthand detection to use -V instead of -v (#2301)
Fixes a regression introduced in eda2be6350 (but not yet released to users). (`-v` is a real flag, but it's an alias for `--verbose`, not `--version`.)

Closes #2299.
2023-01-28 10:47:47 -05:00
Charlie Marsh
8038d32649 Deploy under docs subdirectory 2023-01-28 10:28:40 -05:00
Charlie Marsh
0362cc1098 Allow manual trigger for docs 2023-01-28 10:24:52 -05:00
Charlie Marsh
860e3110c0 Serve docs under /docs subdirectory 2023-01-28 10:22:35 -05:00
Jonxslays
0fa8c578cb Fix typo in typing_extensions (#2298) 2023-01-28 10:03:54 -05:00
Charlie Marsh
861df12269 Preserve global binding kind during reassignments (#2297) 2023-01-28 08:40:09 -05:00
Charlie Marsh
071e3fd196 Split MkDocs site into multiple pages (#2296) 2023-01-28 08:31:16 -05:00
Martin Fischer
dd79ec293a Rename new explain subcommand to rule
We probably want to introduce multiple explain subcommands and
overloading `explain` to explain it all seems like a bad idea.
We may want to introduce a subcommand to explain config options and
config options may end up having the same name as their rules, e.g. the
current `banned-api` is both a rule name (although not yet exposed to
the user) and a config option.

The idea is:

* `ruff rule` lists all rules supported by ruff
* `ruff rule <code>` explains a specific rule
* `ruff linter` lists all linters supported by ruff
* `ruff linter <name>` lists all rules/options supported by a specific linter

(After this commit only the 2nd case is implemented.)
2023-01-28 07:26:20 -05:00
Martin Fischer
5d331e43bf fix: help text and env for --format option of explain subcommand
The doc comment and the env attribute were copied by mistake.
2023-01-28 07:26:20 -05:00
Martin Fischer
ff3563b8ce Remove --check alias introduced in eda2be63
We do not want to support the --{subcommand} legacy format for new
subcommands ... only for subcommands that used this format previously.
2023-01-28 07:26:20 -05:00
Matt Morris
caada2f8bb add missing backticks to flake8 plugin urls in README (#2291) 2023-01-28 07:16:23 -05:00
messense
0b4cc5ac12 Add readme field to pyproject.toml (#2293) 2023-01-28 07:14:58 -05:00
Charlie Marsh
8c70247188 Switch to red MkDocs theme 2023-01-27 23:15:49 -05:00
Charlie Marsh
eaac3cae5e Add MkDocs version of README (#2287)
Co-authored-by: Justin Flannery <juftin@juftin.com>
2023-01-27 22:57:42 -05:00
Charlie Marsh
fd56414b2f Re-add ALL disclaimer 2023-01-27 22:18:20 -05:00
Martin Fischer
9731f96fb4 fix: typo in BREAKING_CHANGES.md & improve wrapping 2023-01-27 21:35:41 -05:00
Charlie Marsh
1a0191f1ac Add release to breaking changes 2023-01-27 20:34:24 -05:00
Charlie Marsh
249cf73d4e Tweak some wording in CLI help (#2285) 2023-01-27 20:25:58 -05:00
Martin Fischer
eda2be6350 Use subcommands for CLI instead of incompatible boolean flags
This commit greatly simplifies the implementation of the CLI,
as well as the user expierence (since --help no longer lists all
options even though many of them are in fact incompatible).

To preserve backwards-compatability as much as possible aliases have
been added for the new subcommands, so for example the following two
commands are equivalent:

    ruff explain E402 --format json
    ruff --explain E402 --format json

However for this to work the legacy-format double-dash command has to
come first, i.e. the following no longer works:

    ruff --format json --explain E402

Since ruff previously had an implicitly default subcommand,
this is preserved for backwards compatibility, i.e. the following two
commands are equivalent:

    ruff .
    ruff check .

Previously ruff didn't complain about several argument combinations that
should have never been allowed, e.g:

    ruff --explain RUF001 --line-length 33

previously worked but now rightfully fails since the explain command
doesn't support a `--line-length` option.
2023-01-27 19:38:17 -05:00
Charlie Marsh
57a68f7c7d Document the location of the personal config file (#2283) 2023-01-27 19:25:55 -05:00
Charlie Marsh
a19dd9237b Add comparison to type checkers (#2282) 2023-01-27 19:18:40 -05:00
Simon Brugman
4f067d806e add clippy and rust_dev to pre-commit (#2256)
I presume the reasoning for not including clippy in `pre-commit` was that it passes all files. This can be turned off with `pass_filenames`, in which case it only runs once.

`cargo +nightly dev generate-all` is also added (when excluding `target` is does not give false positives).

(The overhead of these commands is not much when the build is there. People can always choose to run only certain hooks with `pre-commit run [hook] --all-files`)
2023-01-27 18:53:44 -05:00
Samuel Cormier-Iijima
dd15c69181 [flake8-bandit] Add Rule S110 (try/except/pass) (#2197) 2023-01-27 18:52:55 -05:00
Charlie Marsh
b692921160 Use rustup show in lieu of actions-rs/toolchain (#2280) 2023-01-27 18:51:41 -05:00
Charlie Marsh
b3e8b1b787 Expand heuristic for detecting logging calls (#2279) 2023-01-27 18:41:16 -05:00
Charlie Marsh
0b34ca7107 Move off nightly Rust for dev workflows (#2278) 2023-01-27 18:35:19 -05:00
Charlie Marsh
df44c5124e Add missing autofix levels to sometimes-fixable rules 2023-01-27 18:25:23 -05:00
Simon Brugman
0e27f78b3f feat: include os.getcwdb (bytes) into flake8-use-pathlib (#2276) 2023-01-27 18:25:02 -05:00
Florian Best
cd8ad1df08 mark some fixers as sometimes-fixable (#2271) 2023-01-27 18:23:32 -05:00
Charlie Marsh
d1aaf16e40 Omit typing module from flake8-type-checking by default (#2277) 2023-01-27 18:19:45 -05:00
Ville Skyttä
7320058ce2 Incompatiblity warning updates (#2272) 2023-01-27 18:17:23 -05:00
Aarni Koskela
3a8b367b1c flake8-annotations: Move has_any_typed_arg into correct nested if (#2269) 2023-01-27 18:15:46 -05:00
Ville Skyttä
221b87332c feat: add more DTZ fix suggestions in messages (#2274) 2023-01-27 18:14:17 -05:00
Franck Nijhof
8149c8cbc4 Treat attribute constants as constant for yoda-conditions (#2266)
Accessed attributes that are Python constants should be considered for yoda-conditions


```py
## Error
JediOrder.YODA == age  # SIM300

## OK
age == JediOrder.YODA
```

~~PS: This PR will fail CI, as the `main` branch currently failing.~~
2023-01-27 12:55:12 -05:00
Charlie Marsh
2c415016a6 Update F401 snapshots 2023-01-27 12:43:42 -05:00
Sladyn
bb85119ba8 Convert UnusedImport violation to struct fields (#2141) 2023-01-27 11:31:39 -05:00
Simon Brugman
94551a203e feat: pylint PLE0604 and PLE0605 (#2241) 2023-01-27 11:26:33 -05:00
Charlie Marsh
64c4e4c6c7 Treat constant tuples as constants for yoda-conditions (#2265) 2023-01-27 11:25:57 -05:00
Charlie Marsh
84e4b7c96f Treat builtins as synthetically used (#2251) 2023-01-27 11:25:45 -05:00
Franck Nijhof
ca26f664ec Fix SIM300 to take Python constants into account (#2255)
SIM300 currently doesn't take Python constants into account when looking for Yoda conditions, this PR fixes that behavior.

```python
# Errors
YODA == age  # SIM300
YODA > age  # SIM300
YODA >= age  # SIM300

# OK
age == YODA
age < YODA
age <= YODA
```

Ref: <https://github.com/home-assistant/core/pull/86793>
2023-01-27 11:20:21 -05:00
Aarni Koskela
779b232db9 Fix typo: RelatveImportsOrder (#2264) 2023-01-27 11:15:43 -05:00
Charlie Marsh
a316b26b49 Rewrite some string-format violation messages (#2242) 2023-01-26 19:42:16 -05:00
Charlie Marsh
685d9ab848 Bump version to 0.0.236 2023-01-26 18:47:00 -05:00
Charlie Marsh
093f9156e1 Wrap return-bool-condition-directly fixes in bool() (#2240) 2023-01-26 18:22:34 -05:00
Charlie Marsh
615e62ae24 Clarify E-category rule support (#2239) 2023-01-26 18:12:28 -05:00
Charlie Marsh
76a0c45773 Track type-checking blocks during tree traversal (#2238) 2023-01-26 18:09:28 -05:00
Charlie Marsh
3ec46f0936 Allow pytest in shebang (#2237) 2023-01-26 17:32:23 -05:00
Charlie Marsh
a6ec2eb044 Avoid removing trailing comments on pass statements (#2235)
This isn't super consistent with some other rules, but... if you have a lone body, with a `pass`, followed by a comment, it's probably surprising if it gets removed. Let's retain the comment.

Closes #2231.
2023-01-26 17:29:13 -05:00
Simon Brugman
9d3a5530af refactor: move violations to linters (#2234) 2023-01-26 17:28:14 -05:00
Simon Brugman
8766e6a666 docs(readme): add featuretools (#2236) 2023-01-26 17:24:45 -05:00
Charlie Marsh
b08367b5a8 Avoid flagging blind exceptions with valid logging (#2232) 2023-01-26 17:05:01 -05:00
Charlie Marsh
98a8330124 Add stylist settings to all LibCST invocations (#2225) 2023-01-26 16:59:33 -05:00
Charlie Marsh
4d52ea87ef Implement exempt-modules setting from flake8-type-checking (#2230) 2023-01-26 16:55:32 -05:00
Charlie Marsh
291239b9f1 Fix range for try-consider-else (#2228) 2023-01-26 16:36:18 -05:00
Charlie Marsh
224334b6d1 Avoid erroneous class autofixes in indented blocks (#2226) 2023-01-26 16:24:21 -05:00
Charlie Marsh
0cab3f8437 Preserve indentation when fixing via LibCST (#2223) 2023-01-26 16:09:35 -05:00
Charlie Marsh
5f8810e987 Add strictness setting for flake8-typing-imports (#2221) 2023-01-26 16:04:21 -05:00
Charlie Marsh
f15c562a1c Remove unused overridden property (#2217) 2023-01-26 14:46:46 -05:00
Martin Fischer
4f3b63edd4 fix: --explain reporting the wrong linter
Fixes a regression introduced in 4e4643aa5d.

We want the longest prefixes to be checked first so we of course
have to reverse the sorting when sorting by prefix length.

Fixes #2210.
2023-01-26 13:53:35 -05:00
Simon Brugman
bab8691132 chore: fix script indent (#2213) 2023-01-26 13:53:22 -05:00
Charlie Marsh
50c85fd192 Add a fixable and unfixable example to the docs (#2211) 2023-01-26 13:23:21 -05:00
Martin Fischer
23819ae338 Group options in --help output and sort them by importance
`ruff --help` previously listed 37 options in no particular order
(with niche options like --isolated being listed before before essential
options such as --select).  This commit remedies that and additionally
groups the options by making use of the Clap help_heading feature.

Note that while the source code has previously also referred to
--add-noqa, --show-settings, and --show-files as "subcommands"
this commit intentionally does not list them under the new
Subcommands section since contrary to --explain and --clean
combining them with most of the other options makes sense.
2023-01-26 13:06:29 -05:00
Martin Fischer
4bf2879067 refactor: Move add_noqa if branch up 2023-01-26 13:06:29 -05:00
Martin Fischer
b359f3a9ff refactor: Get rid of ruff::resolver::FileDiscovery 2023-01-26 13:06:29 -05:00
Martin Fischer
73d0461d55 refactor: Check required_version in Settings::from_configuration
The idiomatic way in Rust is to make invalid types unrepresentable
instead of paranoidly calling a validate method everywhere.
2023-01-26 13:06:29 -05:00
Martin Fischer
55bb36fb8b refactor: Introduce LogLevelArgs 2023-01-26 13:06:29 -05:00
Martin Fischer
cebea16fe4 refactor: Move Args::partition call after panic::set_hook 2023-01-26 13:06:29 -05:00
Charlie Marsh
f7be192f8b Alphabetize Flake8 plugins in the README (#2209) 2023-01-26 13:05:30 -05:00
Edgar R. M
e88275280b Implement some rules from flake8-logging-format (#2150) 2023-01-26 12:58:10 -05:00
Samuel Cormier-Iijima
7370a27c09 Don't flag B009/B010 if identifiers would be mangled (#2204) 2023-01-26 12:56:18 -05:00
jvstme
0ad6b8224d Fix typo in src option docs (#2201) 2023-01-26 12:23:09 -05:00
Henry Schreiner
f3aa409d9a docs(readme): add pypa's build (#2200) 2023-01-26 12:18:04 -05:00
Charlie Marsh
adb5c5b150 Fix respect_gitignore reference (#2196) 2023-01-26 09:53:17 -05:00
Martin Fischer
b69b6a7ec8 refactor: Move comments before if conditions 2023-01-25 22:08:35 -05:00
Martin Fischer
a7d2def9cd refactor: Move ruff_cli::resolve to own module 2023-01-25 22:08:35 -05:00
Martin Fischer
d9ead4e6df refactor: Rename CLI arg structs from Cli to Args
Technically the command-line interface (CLI) encompasses both input and
output, so naming the input structs 'Args' is more accurate than 'Cli'.
2023-01-25 22:08:35 -05:00
Charlie Marsh
b346f74915 Run cargo update (#2185) 2023-01-25 21:32:44 -05:00
Eric Roberts
708295f4c9 Move violations for pycodestyle rules to rules files (#2138) 2023-01-25 20:11:36 -05:00
Charlie Marsh
4190f1045e Remove manual newline from autofix helpers (#2184) 2023-01-25 19:53:26 -05:00
Florian Stasse
353857e2a5 Implement TRY400 (#2115) 2023-01-25 19:42:19 -05:00
Denis Gavrilyuk
55b43c8ea7 feat: implement TRY002 and TRY003 (#2135) 2023-01-25 19:22:43 -05:00
Anders Kaseorg
6036d1bbe2 flake8_executable: Only match shebang at beginning of line (#2183)
The Python implementation uses `re.match` for this, which only matches
at the beginning of a line.

https://github.com/xuhdev/flake8-executable/blob/v2.1.3/flake8_executable/__init__.py#L124

We could use `Regex::captures_read_at`, but that’s a more complicated
API; it’s easier to anchor the regex with `^`.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-25 18:57:09 -05:00
Charlie Marsh
edd0e16a02 Bump version to 0.0.235 2023-01-25 18:28:27 -05:00
Charlie Marsh
fdccb6ec1c Fix conflicting error message warning (#2182) 2023-01-25 18:26:43 -05:00
Anders Kaseorg
c00b8b6d2d Remove stray parenthesis from fixed errors message (#2181)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-25 18:15:12 -05:00
Simon Brugman
52201422ae fix: platform-independent newlines 2023-01-25 18:00:39 -05:00
Simon Brugman
d7fe1eeba0 fix: platform-independent paths 2023-01-25 18:00:39 -05:00
Simon Brugman
5835d719c4 ci: enable windows testing in Github Actions 2023-01-25 18:00:39 -05:00
Simon Brugman
c859ac4933 refactor: test ground truth update for new macro 2023-01-25 18:00:39 -05:00
Simon Brugman
e9c1089ddc refactor: tests use new marco 2023-01-25 18:00:39 -05:00
Simon Brugman
413acdf83c feat: introduce macro for testing snap files across platforms 2023-01-25 18:00:39 -05:00
Charlie Marsh
16d2ece87d Restore single-file license (#2180)
These were split into per-project licenses in #1648, but I don't like that they're no longer included in the distribution (due to current limitations in the `pyproject.toml` spec).
2023-01-25 17:59:12 -05:00
Anders Kaseorg
823f1c5b6a Avoid duplicate CI runs triggered by pushes to pull requests (#2178)
https://github.com/charliermarsh/ruff/pull/2157#discussion_r1087179996

Signed-off-by: Anders Kaseorg <andersk@mit.edu>

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-25 17:45:07 -05:00
Charlie Marsh
9b07d0bd92 Bump version to 0.0.234 2023-01-25 16:55:57 -05:00
Charlie Marsh
23525a8ea0 Actually, rename TYP rules to TCH (#2176) 2023-01-25 16:52:49 -05:00
Charlie Marsh
6ede030700 Allow manual releases for pre-release testing 2023-01-25 16:37:04 -05:00
Charlie Marsh
44f3e5013d Add flake8-type-checking license 2023-01-25 16:27:18 -05:00
Charlie Marsh
35cf9e242e Rename TYP rules to TYC (#2175) 2023-01-25 16:26:22 -05:00
Charlie Marsh
d5dff11d4b Avoid reraise-no-cause for explicit reraises (#2174) 2023-01-25 15:51:24 -05:00
Charlie Marsh
8e1fac620e Add flake8-builtins options to README (#2173) 2023-01-25 15:43:26 -05:00
Aarni Koskela
0da691c0d5 Add Babel to readme (#2170) 2023-01-25 15:21:26 -05:00
Hugo van Kemenade
233415921b Add colour to CI for readability 2023-01-25 15:21:10 -05:00
Hugo van Kemenade
81141e2a73 Bump GitHub Actions 2023-01-25 15:21:10 -05:00
Hugo van Kemenade
6e255ad53c Allow testing feature branches 2023-01-25 15:21:10 -05:00
Hugo van Kemenade
6d87adbcc0 Fix singular and plural for error(s) 2023-01-25 15:21:10 -05:00
Florian Best
43a8ce6c89 fix: avoid flagging unused loop variable (B007) with globals(), vars() or eval() (#2166) 2023-01-25 15:18:58 -05:00
Charlie Marsh
a978706dce Re-add error wrapper in main.rs (#2168) 2023-01-25 15:11:24 -05:00
Florian Best
dc1aa8dd1d Suggest input format in error case (#2167) 2023-01-25 14:55:04 -05:00
Charlie Marsh
662e29b1ce Avoid re-resolving settings for repeated paths (#2165)
After this change:

```shell
> time cargo run -- -n $(find ../django -type f -name '*.py')`
8.85s user 0.20s system 498% cpu 1.814 total
> time cargo run -- -n ../django
8.95s user 0.23s system 507% cpu 1.811 total
```

I also verified that we only hit the creation path once via some manual logging.

Closes #2154.
2023-01-25 13:38:33 -05:00
Charlie Marsh
6978dcf035 Add an FAQ on autofix (#2163) 2023-01-25 13:09:16 -05:00
Charlie Marsh
0e6f513607 Avoid prefer-type-error (TRY004) with intermediary control flow (#2162) 2023-01-25 13:00:59 -05:00
Charlie Marsh
02421d02f5 Avoid flagging unused loop variable (B007) with locals() (#2161) 2023-01-25 12:53:35 -05:00
Charlie Marsh
38de46ae3c Treat Python 3.7 as minimum supported version (#2159) 2023-01-25 12:36:50 -05:00
Martin Fischer
f6fd702d41 Add #![warn(clippy::pedantic)] to lib.rs and main.rs files
We already enforced pedantic clippy lints via the
following command in .github/workflows/ci.yaml:

    cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic

Additionally adding #![warn(clippy::pedantic)] to all main.rs and lib.rs
has the benefit that violations of pedantic clippy lints are also
reported when just running `cargo clippy` without any arguments and
are thereby also picked up by LSP[1] servers such as rust-analyzer[2].
However for rust-analyzer to run clippy you'll have to configure:

    "rust-analyzer.check.command": "clippy",

in your editor.[3]

[1]: https://microsoft.github.io/language-server-protocol/
[2]: https://rust-analyzer.github.io/
[3]: https://rust-analyzer.github.io/manual.html#configuration
2023-01-25 00:40:29 -05:00
Martin Fischer
2125d0bb54 refactor: Move #![forbid(unsafe_code)] attributes up
What's forbidden is more important than which clippy lints are
ignored and more important directives should come first.
2023-01-25 00:40:29 -05:00
Charlie Marsh
63b4f60ba4 Implement typing-only import detection (TYP001, TYP002, TYP003) (#2147) 2023-01-24 23:48:11 -05:00
Charlie Marsh
9eb13bc9da Downgrade recommended pre-commit version to v0.0.231 2023-01-24 23:47:13 -05:00
Charlie Marsh
0758049e49 Implement runtime-import-in-type-checking-block (TYP004) (#2146) 2023-01-24 23:33:26 -05:00
Charlie Marsh
deff503932 Avoid generating dirty call paths (#2144) 2023-01-24 20:40:38 -05:00
Jonathan Plasse
82d7814101 Update .pre-commit-config.yml (#2139) 2023-01-24 19:45:34 -05:00
Eric Roberts
0cac1a0d21 Move is_overlong to helpers (#2137) 2023-01-24 12:45:35 -05:00
Charlie Marsh
605416922d Bump version to 0.0.233 2023-01-24 10:46:49 -05:00
Charlie Marsh
7b81f36e54 Enable executable checks on Windows (#2133) 2023-01-24 10:46:27 -05:00
Eric Roberts
ff63da9f52 Move compare to helpers file (#2131)
From discussion on https://github.com/charliermarsh/ruff/pull/2123

I didn't originally have a helpers file so I put the function in both
places but now that a helpers file exists it seems logical for it to be
there.
2023-01-24 10:30:56 -05:00
Charlie Marsh
d645a19e0a Bump version to 0.0.232 2023-01-24 09:49:07 -05:00
Charlie Marsh
30ae0d3723 Add Dagger and Great Expectations (#2130) 2023-01-24 09:48:00 -05:00
Charlie Marsh
3fb9e76012 Remove unnecessary manual Generator invocations (#2129) 2023-01-24 09:38:12 -05:00
Eric Roberts
0f283ae98c Move pycodestyle rules into individual files (#2123) 2023-01-24 09:27:26 -05:00
Martin Fischer
269926cec4 refactor: Move redirects out of RuleCodePrefix
This commit removes rule redirects such as ("U" -> "UP") from the
RuleCodePrefix enum because they complicated the generation of that enum
(which we want to change to be prefix-agnostic in the future).

To preserve backwards compatibility redirects are now resolved
before the strum-generated RuleCodePrefix::from_str is invoked.

This change also brings two other advantages:

* Redirects are now only defined once
  (previously they had to be defined twice:
  once in ruff_macros/src/rule_code_prefix.rs
  and a second time in src/registry.rs).

* The deprecated redirects will no longer be suggested in IDE
  autocompletion within pyproject.toml since they are now no
  longer part of the ruff.schema.json.
2023-01-24 09:26:19 -05:00
Martin Fischer
28018442f6 refactor: Move ALL from RuleCodePrefix to RuleSelector 2023-01-24 09:26:19 -05:00
Martin Fischer
abc9810e2b refactor: Turn RuleSelector into a newtype around RuleCodePrefix
Yet another refactor to let us implement the many-to-many mapping
between codes and rules in a prefix-agnostic way.

We want to break up the RuleCodePrefix[1] enum into smaller enums.
To facilitate that this commit  introduces a new wrapping type around
RuleCodePrefix so that we can start breaking it apart.

[1]: Actually `RuleCodePrefix` is the previous name of the autogenerated
enum ... I renamed it in b19258a243 to
RuleSelector since `ALL` isn't a prefix. This commit now renames it back
but only because the new `RuleSelector` wrapper type, introduced in this
commit, will let us move the `ALL` variant from `RuleCodePrefix` to
`RuleSelector` in the next commit.
2023-01-24 09:26:19 -05:00
Charlie Marsh
a20482961b Add tryceratops to flake8-to-ruff 2023-01-24 08:41:18 -05:00
Charlie Marsh
d97c07818e Update flake8-to-ruff to include latest plugins (#2127)
Closes #2124 (along with a release).
2023-01-24 08:39:58 -05:00
Ville Skyttä
7e92485f43 feat: autofix multi-line-summary-*-line (#2093) 2023-01-24 08:17:13 -05:00
Charlie Marsh
930c3be69d Ignore generators in flake8-return rules (#2126)
We could do a better job of handling them, but they cause too many false-positives right now.

Closes #2119.
2023-01-24 08:15:26 -05:00
Aarni Koskela
24d0a980c5 flake8-annotations: deduplicate code between functions and methods (#2125) 2023-01-24 08:03:33 -05:00
Edgar R. M
f5f0ed280a Implement EXE001 and EXE002 from flake8-executable (#2118) 2023-01-24 08:02:47 -05:00
Martin Fischer
ca58c72fc9 refactor: Convention::codes to rules_to_be_ignored 2023-01-24 07:37:34 -05:00
Martin Fischer
c40f14620a refactor: Get rid of registry::CATEGORIES 2023-01-24 07:37:34 -05:00
Martin Fischer
04300ce258 refactor: Rename SuffixLength enum to Specificity 2023-01-24 07:37:34 -05:00
Martin Fischer
ead5f948d3 refactor: Move Colorize imports where they're used 2023-01-24 07:37:34 -05:00
Martin Fischer
e93e9fae82 refactor: Make flake8_to_ruff tests even more DRY 2023-01-24 07:37:34 -05:00
Martin Fischer
f5ddec0fb3 refactor: Move resolve_select to converter module
The function is only used there and is not plugin-specific
since it also specifies the default rule selectors (F, E, W).
2023-01-24 07:37:34 -05:00
Martin Fischer
3de2a57416 refactor: Use ..Options::default() for tests 2023-01-24 07:37:34 -05:00
Hugo
b29b4084ff Add apk instructions to README (#2121) 2023-01-24 07:29:03 -05:00
Aarni Koskela
c61ca4a953 Add Home Assistant to Readme (#2120) 2023-01-24 07:27:45 -05:00
Denis Gavrilyuk
58d5ac08a8 feat: implement TRY301 (#2113) 2023-01-24 07:25:26 -05:00
Charlie Marsh
cc63a4be6a Allow flagging of multiline implicit string concatenations (#2117)
At present, `ISC001` and `ISC002` flag concatenations like the following:

```py
"a" "b"  # ISC001
"a" \
  "b"  # ISC002
```

However, multiline concatenations are allowed.

This PR adds a setting:

```toml
[tool.ruff.flake8-implicit-str-concat]
allow-multiline = false
```

Which extends `ISC002` to _also_ flag multiline concatenations, like:

```py
(
  "a"  # ISC002
  "b"
)
```

Note that this is backwards compatible, as `allow-multiline` defaults to `true`.
2023-01-24 00:01:01 -05:00
Charlie Marsh
549a5d44bc Upgrade to toml v0.6.0 (#2116)
Closes #1894.
2023-01-23 19:22:42 -05:00
Denis Gavrilyuk
d65ce6308b feat: implement TRY200 (#2087)
#2056
2023-01-23 14:12:42 -05:00
Charlie Marsh
b988a268e4 Escape curly braces when converting .format() strings (#2112)
Closes #2111.
2023-01-23 14:11:24 -05:00
Charlie Marsh
1c3265ef98 Bump version to 0.0.231 2023-01-23 12:51:09 -05:00
Maksudul Haque
8001a1639c [flake8-bandit] Added Rule S612 (Use of insecure logging.config.listen) (#2108)
ref: https://github.com/charliermarsh/ruff/issues/1646
2023-01-23 12:37:33 -05:00
Charlie Marsh
7d9c1d7a5a Add a note on some isort incompatibilities 2023-01-23 12:32:35 -05:00
Thomas MK
c5cebb106e Fix outdated description of ruff's support of isort settings (#2106)
Ruff supports more than `known-first-party`, `known-third-party`, `extra-standard-library`, and `src` nowadays.

Not sure if this is the best wording. Suggestions welcome!
2023-01-23 12:29:44 -05:00
Martin Fischer
8c61e8a1ef Improve #[derive(RuleNamespace)] error handling 2023-01-23 12:20:10 -05:00
Martin Fischer
4f338273a5 refactor: Simplify test_ruff_black_compatibility 2023-01-23 12:20:10 -05:00
Martin Fischer
648191652d refactor: Collect into Result<Vec<_>, _> 2023-01-23 12:20:10 -05:00
Martin Fischer
90558609c3 refactor: Introduce parse_doc_attr helper function 2023-01-23 12:20:10 -05:00
Martin Fischer
991d3c1ef6 refactor: Move Linter::url and Linter::name generation to proc macro
This lets us get rid of the build.rs script and results
in more developer-friendly compile error messages.
2023-01-23 12:20:10 -05:00
Simon Brugman
f472fbc6d4 docs(readme): add pypa cibuildwheel (#2107) 2023-01-23 11:39:23 -05:00
Charlie Marsh
09b65a6449 Remove some usages of default format for expressions (#2100) 2023-01-22 23:15:43 -05:00
Charlie Marsh
9d2eced941 Add flake8-simplify to CONTRIBUTING.md 2023-01-22 21:46:52 -05:00
Charlie Marsh
be0f6acb40 Change contributing to point to tryceratops 2023-01-22 21:45:20 -05:00
Steve Dignam
0c624af036 Add flake8-pie PIE800: no-unnecessary-spread (#1881)
Checks for unnecessary spreads, like `{**foo, **{"bar": True}}`
rel: https://github.com/charliermarsh/ruff/issues/1879
rel: https://github.com/charliermarsh/ruff/issues/1543
2023-01-22 21:43:34 -05:00
Steve Dignam
4ca328f964 Add flake8-pie PIE804: no-unnecessary-dict-kwargs (#1884)
Warn about things like `foo(**{"bar": True})` which is equivalent to `foo(bar=True)`

rel: https://github.com/charliermarsh/ruff/issues/1879
rel: https://github.com/charliermarsh/ruff/issues/1543
2023-01-22 21:32:45 -05:00
Charlie Marsh
07b5bf7030 Remove misleading emoji comment 2023-01-22 21:23:55 -05:00
Charlie Marsh
f40ae943a7 Fix bad documentation message for init option 2023-01-22 19:25:23 -05:00
Charlie Marsh
8d46d3bfa6 Avoid nested-if violations when outer-if has else clause (#2095)
It looks like we need `do`-`while`-like semantics here with an additional outer check.

Closes #2094.
2023-01-22 17:40:56 -05:00
alm
4fb0c6e3ad feat: Implement TRY201 (#2073) 2023-01-22 17:08:57 -05:00
Simon Brugman
ebfdefd110 refactor: remove redundant enum (#2091) 2023-01-22 15:27:08 -05:00
Simon Brugman
11f06055a0 feat: flake8-use-pathlib PTH100-124 (#2090) 2023-01-22 15:17:25 -05:00
Ville Skyttä
6a6a792562 fix: issue D401 only for non-test/property functions and methods (#2071)
Extend test fixture to verify the targeting.

Includes two "attribute docstrings" which per PEP 257 are not recognized by the Python bytecode compiler or available as runtime object attributes. They are not available for us either at time of writing, but include them for completeness anyway in case they one day are.
2023-01-22 14:24:59 -05:00
Charlie Marsh
23b622943e Bump version to 0.0.230 2023-01-22 13:58:41 -05:00
Harutaka Kawamura
a7ce8621a9 Update RustPython to fix Dict.keys type (#2086)
This PR upgrades RustPython to fix the type of `Dict.keys` to `Vec<Option<Expr>>` (see https://github.com/RustPython/RustPython/pull/4449 for why this change was needed) and unblock #1884.
2023-01-22 13:24:00 -05:00
Shannon Rothe
36fb8f7a63 flake8_to_ruff: support isort options (#2082)
See: https://github.com/charliermarsh/ruff/issues/1749.
2023-01-22 13:18:01 -05:00
alm
e11cf1bf65 Update linters PyPI links to latest version (#2062) 2023-01-22 13:10:22 -05:00
Maksudul Haque
75e16c0ce5 [pep8-naming][N806] Don't mark TypeVar & NewType Assignment as Errors (#2085)
closes https://github.com/charliermarsh/ruff/issues/1985
2023-01-22 12:54:13 -05:00
Martin Fischer
1beedf20f9 fix: add_rule.py for --linter ruff 2023-01-22 11:51:29 -05:00
Martin Fischer
4758ee6ac4 refactor: Generate Linter -> RuleSelector mapping via macro
To enable ruff_dev to automatically generate the rule Markdown tables in
the README the ruff library contained the following function:

    Linter::codes() -> Vec<RuleSelector>

which was slightly changed to `fn prefixes(&self) -> Prefixes` in
9dc66b5a65 to enable ruff_dev to split
up the Markdown tables for linters that have multiple prefixes
(pycodestyle has E & W, Pylint has PLC, PLE, PLR & PLW).

The definition of this method was however largely redundant with the
#[prefix] macro attributes in the Linter enum, which are used to
derive the Linter::parse_code function, used by the --explain command.

This commit removes the redundant Linter::prefixes by introducing a
same-named method with a different signature to the RuleNamespace trait:

     fn prefixes(&self) -> &'static [&'static str];

As well as implementing IntoIterator<Rule> for &Linter. We extend the
extisting RuleNamespace proc macro to automatically derive both
implementations from the Linter enum definition.

To support the previously mentioned Markdown table splitting we
introduce a very simple hand-written method to the Linter impl:

    fn categories(&self) -> Option<&'static [LinterCategory]>;
2023-01-22 11:51:29 -05:00
Martin Fischer
c3dd1b0e3c refactor: Rename ParseCode trait to RuleNamespace
ParseCode was a fitting name since the trait only contained a single
parse_code method ... since we now however want to introduce an
additional `prefixes` method RuleNamespace is more fitting.
2023-01-22 11:51:29 -05:00
Martin Fischer
87443e6301 Support prefix "PL" to select all of Pylint 2023-01-22 11:51:29 -05:00
Martin Fischer
16d2ceba79 refactor: Avoid unnecessary Map indexing 2023-01-22 11:51:29 -05:00
Martin Fischer
aedee7294e refactor: Stop using Ident as BTreeMap key
Using Ident as the key type is inconvenient since creating an Ident
requires the specification of a Span, which isn't actually used by
the Hash implementation of Ident.
2023-01-22 11:51:29 -05:00
Martin Fischer
4f12b31dc8 refactor: Drop RuleSelector::codes in favor of IntoIterator impl 2023-01-22 11:51:29 -05:00
Martin Fischer
9f14e7c830 refactor: Update some variable/field/method names 2023-01-22 11:51:29 -05:00
Martin Fischer
4cc492a17a refactor: Encapsulate PerFileIgnore impl details 2023-01-22 11:51:29 -05:00
Martin Fischer
028436af81 refactor: Group Configuration struct fields 2023-01-22 11:51:29 -05:00
Martin Fischer
da4994aa73 refactor: impl From<&Configuration> for RuleTable 2023-01-22 11:51:29 -05:00
Martin Fischer
4dcb491bec refactor: Avoid some unnecessary allocations 2023-01-22 11:51:29 -05:00
Simon Brugman
6fc6bf0648 feat: enable autofix for TRY004 (#2084)
functionality was already implemented, just the trait needed to be added
2023-01-22 07:18:56 -05:00
Charlie Marsh
c1cb4796f8 Support decorators in source code generator (#2081) 2023-01-21 23:26:32 -05:00
Charlie Marsh
d81620397e Improve generator precedence operations (#2080) 2023-01-21 23:21:37 -05:00
Charlie Marsh
84b1490d03 Base INP check on package inference (#2079)
If a file doesn't have a `package`, then it must both be in a directory that lacks an `__init__.py`, and a directory that _isn't_ marked as a namespace package.

Closes #2075.
2023-01-21 19:49:56 -05:00
Simon Brugman
28f05aa6e7 feat: update scripts to new rules structure (#2078)
- optional `prefix` argument for `add_plugin.py`
- rules directory instead of `rules.rs`
- pathlib syntax
- fix test case where code was added instead of name

Example:
```
python scripts/add_plugin.py --url https://pypi.org/project/example/1.0.0/ example --prefix EXA
python scripts/add_rule.py --name SecondRule --code EXA002 --linter example
python scripts/add_rule.py --name FirstRule --code EXA001 --linter example
python scripts/add_rule.py --name ThirdRule --code EXA003 --linter example
 ```

Note that it breaks compatibility with 'old style' plugins (generation works fine, but namespaces need to be changed):
```
python scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
```
2023-01-21 19:19:58 -05:00
Charlie Marsh
325faa8e18 Include package path in cache key (#2077)
Closes #2075.
2023-01-21 18:33:35 -05:00
Charlie Marsh
6bfa1804de Remove remaining ropey usages (#2076) 2023-01-21 18:24:10 -05:00
Charlie Marsh
4dcf284a04 Index source code upfront to power (row, column) lookups (#1990)
## Summary

The problem: given a (row, column) number (e.g., for a token in the AST), we need to be able to map it to a precise byte index in the source code. A while ago, we moved to `ropey` for this, since it was faster in practice (mostly, I think, because it's able to defer indexing). However, at some threshold of accesses, it becomes faster to index the string in advance, as we're doing here.

## Benchmark

It looks like this is ~3.6% slower for the default rule set, but ~9.3% faster for `--select ALL`.

**I suspect there's a strategy that would be strictly faster in both cases**, based on deferring even more computation (right now, we lazily compute these offsets, but we do it for the entire file at once, even if we only need some slice at the top), or caching the `ropey` lookups in some way.

Before:

![main](https://user-images.githubusercontent.com/1309177/213883581-8f73c61d-2979-4171-88a6-a88d7ff07e40.png)

After:

![48 all](https://user-images.githubusercontent.com/1309177/213883586-3e049680-9ef9-49e2-8f04-fd6ff402eba7.png)

## Alternatives

I tried tweaking the `Vec::with_capacity` hints, and even trying `Vec::with_capacity(str_indices::lines_crlf::count_breaks(contents))` to do a quick scan of the number of lines, but that turned out to be slower.
2023-01-21 17:56:11 -05:00
Zeddicus414
08fc9b8095 ICN001 check from imports that have no alias (#2072)
Add tests.

Ensure that these cases are caught by ICN001:
```python
from xml.dom import minidom
from xml.dom.minidom import parseString
```

with config:
```toml
[tool.ruff.flake8-import-conventions.extend-aliases]
"dask.dataframe" = "dd"
"xml.dom.minidom" = "md"
"xml.dom.minidom.parseString" = "pstr"
```
2023-01-21 17:47:08 -05:00
Cosmo
39aed6f11d Update link to Pylint parity tracking issue (#2074) 2023-01-21 17:46:55 -05:00
Zeddicus414
5726118cfe ICN001 import-alias-is-not-conventional should check "from" imports (#2070)
Closes https://github.com/charliermarsh/ruff/issues/2047.
2023-01-21 15:43:51 -05:00
Simon Brugman
67de8ac85e feat: implementation for TRY004 (#2066)
See: #2056.
2023-01-21 14:58:59 -05:00
figsoda
b1bda0de82 fix: pin rustpython to the same revision to fix cargo vendor (#2069)
I was trying to update ruff in nixpkgs and ran into this error when it was running `cargo vendor`
```
error: failed to sync

Caused by:
  found duplicate version of package `rustpython-ast v0.2.0` vendored from two sources:

        source 1: https://github.com/RustPython/RustPython.git?rev=62aa942bf506ea3d41ed0503b947b84141fdaa3c#62aa942b
        source 2: https://github.com/RustPython/RustPython.git?rev=ff90fe52eea578c8ebdd9d95e078cc041a5959fa#ff90fe52
```
2023-01-21 14:40:00 -05:00
Charlie Marsh
84300e00ff Bump version to 0.0.229 2023-01-21 13:18:06 -05:00
Charlie Marsh
fbee95a668 Avoid flagging redefined imports as unused in same-scope (#2065)
This is effectively a revert of #1173, to favor false-negatives over false-positives in the same-scope case.

Closes #2044.
2023-01-21 12:50:21 -05:00
Simon Brugman
afcf5c0ee0 feat: plugin scaffold for tryceratops with TRY300 (#2055)
Renamed to TRY to avoid conflicts, as proposed in https://github.com/guilatrova/tryceratops/pull/55

https://github.com/guilatrova/tryceratops/blob/main/docs/violations/TC300.md

See: #2056
2023-01-21 11:25:10 -05:00
Maksudul Haque
0c30768288 [flake8-builtins] Add builtins-ignorelist Option (#2061)
Closes #2053.
2023-01-21 11:09:04 -05:00
Colin Delahunty
80295f335b Pyupgrade: Printf string formatting (#1803) 2023-01-21 09:37:22 -05:00
Charlie Marsh
465943adf7 Revert "Upgrade to toml v0.5.11" (#2058)
This _did_ fix https://github.com/charliermarsh/ruff/issues/1894, but was a little premature. `toml` doesn't actually depend on `toml-edit` yet, and `v0.5.11` was mostly about deprecations AFAICT. So upgrading might solve that issue, but could introduce other incompatibilities, and I'd like to minimize churn. I expect that `toml` will have a new release soon, so we can revert this revert.

Reverts charliermarsh/ruff#2040.
2023-01-21 07:54:56 -05:00
Charlie Marsh
38eed292e4 Avoid removing comments in RUF005 (#2057)
Closes #2054.
2023-01-21 07:37:25 -05:00
Harutaka Kawamura
883e650a35 Fix S101 range to only highlight assert (#2052)
Fix:

```
resources/test/fixtures/flake8_bandit/S101.py:2:1: S101 Use of `assert` detected
  |
2 | assert True
  | ^^^^^^^^^^^ S101
  |

resources/test/fixtures/flake8_bandit/S101.py:8:5: S101 Use of `assert` detected
  |
8 |     assert x == 1
  |     ^^^^^^^^^^^^^ S101
  |

resources/test/fixtures/flake8_bandit/S101.py:11:5: S101 Use of `assert` detected
   |
11 |     assert x == 2
   |     ^^^^^^^^^^^^^ S101
   |

Found 3 error(s).
```

to:

```
resources/test/fixtures/flake8_bandit/S101.py:2:1: S101 Use of `assert` detected
  |
2 | assert True
  | ^^^^^^ S101
  |

resources/test/fixtures/flake8_bandit/S101.py:8:5: S101 Use of `assert` detected
  |
8 |     assert x == 1
  |     ^^^^^^ S101
  |

resources/test/fixtures/flake8_bandit/S101.py:11:5: S101 Use of `assert` detected
   |
11 |     assert x == 2
   |     ^^^^^^ S101
   |
```
2023-01-21 07:15:00 -05:00
Harutaka Kawamura
eb1b5e5454 De-duplicate SIM102 (#2050)
The idea is the same as #1867. Avoids emitting `SIM102` twice for the following code:

```python
if a:
    if b:
        if c:
            d
```

```
resources/test/fixtures/flake8_simplify/SIM102.py:1:1: SIM102 Use a single `if` statement instead of nested `if` statements
resources/test/fixtures/flake8_simplify/SIM102.py:2:5: SIM102 Use a single `if` statement instead of nested `if` statements
```
2023-01-20 23:38:52 -05:00
Charlie Marsh
8e558a3458 Add scaffolding for flake8-type-checking extension (#2048)
This PR adds the scaffolding files for `flake8-type-checking`, along with the simplest rule (`empty-type-checking-block`), just as an example to get us started.

See: #1785.
2023-01-20 22:41:36 -05:00
Martin Fischer
4e4643aa5d refactor: Decouple Rule from linter prefixes
543865c96b introduced
RuleCode::origin() -> RuleOrigin generation via a macro, while that
signature now has been renamed to Rule::origin() -> Linter we actually
want to get rid of it since rules and linters shouldn't be this tightly
coupled (since one rule can exist in multiple linters).

Another disadvantage of the previous approach was that the prefixes
had to be defined in ruff_macros/src/prefixes.rs, which was easy to
miss when defining new linters in src/*, case in point
INP001 => violations::ImplicitNamespacePackage has in the meantime been
added without ruff_macros/src/prefixes.rs being updated accordingly
which resulted in `ruff --explain INP001` mistakenly reporting that the
rule belongs to isort (since INP001 starts with the isort prefix "I").
The derive proc macro introduced in this commit requires every variant
to have at least one #[prefix = "..."], eliminating such mistakes.
2023-01-20 20:25:57 -05:00
Martin Fischer
b19258a243 refactor: Rename RuleCodePrefix to RuleSelector
More accurate since the enum also encompasses:

* ALL (which isn't a prefix at all)

* fully-qualified rule codes (which aren't prefixes unless you say
  they're a prefix to the empty string but that's not intuitive)
2023-01-20 20:25:57 -05:00
Martin Fischer
7fc42f8f85 refactor: Rename RuleOrigin to Linter
"origin" was accurate since ruff rules are currently always modeled
after one origin (except the Ruff-specific rules).

Since we however want to introduce a many-to-many mapping between codes
and rules, the term "origin" no longer makes much sense. Rules usually
don't have multiple origins but one linter implements a rule first and
then others implement it later (often inspired from another linter).
But we don't actually care much about where a rule originates from when
mapping multiple rule codes to one rule implementation, so renaming
RuleOrigin to Linter is less confusing with the many-to-many system.
2023-01-20 20:25:57 -05:00
Dmitry Dygalo
babe1eb7be perf: Reduce allocations (#2045)
I found a few places where some allocations could be avoided.
2023-01-20 20:06:48 -05:00
Simon Brugman
608b2191aa [flake8-executable] EXE003-005 (#2023)
Tracking issue: https://github.com/charliermarsh/ruff/issues/2024

Implementation for EXE003, EXE004 and EXE005 of `flake8-executable` 
(shebang should contain "python", not have whitespace before, and should be on the first line)

Please take in mind that this is my first rust contribution.

The remaining EXE-rules are a combination of shebang (`lines.rs`), file permissions (`fs.rs`) and if-conditions (`ast.rs`). I was not able to find other rules that have interactions/dependencies in them. Any advice on how this can be best implemented would be very welcome.

For autofixing `EXE005`, I had in mind to _move_  the shebang line to the top op the file. This could be achieved by a combination of `Fix::insert` and `Fix::delete` (multiple fixes per diagnostic), or by implementing a dedicated `Fix::move`, or perhaps in other ways. For now I've left it out, but keen on hearing what you think would be most consistent with the package, and pointer where to start (if at all).

---
If you care about another testimonial:
`ruff` not only helps staying on top of the many excellent flake8 plugins and other Python code quality tools that are available, it also applies them at baffling speed.
(Planning to implement it soon for github.com/pandas-profiling/pandas-profiling (as largest contributor) and github.com/ing-bank/popmon.)
2023-01-20 18:19:07 -05:00
Eric Roberts
3939c2dbf7 Add support for pycodestyle E101 (#2038)
Rule described here: https://www.flake8rules.com/rules/E101.html

I tried to follow contributing guidelines closely, I've never worked with Rust before. Stumbled across Ruff a few days ago and would like to use it in our project, but we use a bunch of flake8 rules that are not yet implemented in ruff, so I decided to give it a go.
2023-01-20 17:24:58 -05:00
Charlie Marsh
20a9252e92 Upgrade to toml v0.5.11 (#2040)
In #1680, we moved over to `toml_edit`. But it looks like `toml` now uses `toml_edit`, and has implemented some improvements (e.g., this closes #1894).
2023-01-20 17:20:45 -05:00
Hugo van Kemenade
a0e3347e43 README: --force-exclude is already set (#2042)
Re: https://github.com/charliermarsh/ruff-pre-commit/issues/19 / https://github.com/charliermarsh/ruff-pre-commit/pull/20

This is now always set, no need to include it in the README example.
2023-01-20 17:20:22 -05:00
Charlie Marsh
9e704a7c63 Only fix true-false returns for return-bool-condition-directly (#2037)
Closes #2035.
2023-01-20 13:17:19 -05:00
Zeddicus414
c9da98e0b7 Fix D404 NoThisPrefix not working with whitespace. (#2036)
D404 should trigger for """ This is a docstring."""

Add a few tests to ensure the fix worked.
2023-01-20 13:01:31 -05:00
Charlie Marsh
5377d24507 Bump version to 0.0.228 2023-01-20 09:58:56 -05:00
Florian Best
db8e4500ee fix(pydocstyle): Avoid trimming docstring if starts with leading quote (#2027)
Fixes: #2017

looks like the other way round is also possible to break:

```""" "foo"""`
2023-01-20 09:57:48 -05:00
Aarni Koskela
bd2de5624e Move readme dev details to CONTRIBUTING.md and fix contradictions (#2030)
Following up on #2018/#2019 discussion, this moves the readme's development-related bits to `CONTRIBUTING.md` to avoid duplication, and fixes up the commands accordingly 😄
2023-01-20 09:23:28 -05:00
Aarni Koskela
3a81f893cc Bump terminfo to remove a whole bunch of unnecessary dependencies (#2022)
See 6281c6b8f7

```
$ cargo update -p terminfo
    Updating crates.io index
    Removing cfg-if v0.1.10
    Removing dirs v2.0.2
    Removing getrandom v0.1.16
    Removing phf v0.8.0
    Updating phf_codegen v0.8.0 -> v0.11.1
    Updating phf_generator v0.8.0 -> v0.11.1
    Removing phf_shared v0.8.0
    Removing rand v0.7.3
    Removing rand_chacha v0.2.2
    Removing rand_core v0.5.1
    Removing rand_hc v0.2.0
    Removing rand_pcg v0.2.1
    Updating terminfo v0.7.3 -> v0.7.5
    Removing wasi v0.9.0+wasi-snapshot-preview1
```
2023-01-20 09:09:02 -05:00
Charlie Marsh
fd6dc2a343 Use platform-appropriate newline character for LibCST embedding (#2028)
Closes #2026.
2023-01-20 09:08:04 -05:00
Martin Fischer
8693236f9e Make CI test add_*.py scripts 2023-01-20 08:09:54 -05:00
Martin Fischer
44e2b6208a fix: Update add_rule.py to create new files for rules 2023-01-20 08:09:54 -05:00
Martin Fischer
16c81f75c2 fix: Update add_rule.py to account for 16e79c8d 2023-01-20 08:09:54 -05:00
Martin Fischer
e1d6ac3265 fix: Update add_plugin.py to account for 9dc66b5a 2023-01-20 08:09:54 -05:00
Martin Fischer
3aec1100f5 fix: Update add_plugin.py to account for b78b6f27 2023-01-20 08:09:54 -05:00
Martin Fischer
c00df647e1 fix: Update add_rule.py to account for 81996f1bc 2023-01-20 08:09:54 -05:00
Martin Fischer
f012877be1 Add scripts/pyproject.toml to use ruff for ruff :) 2023-01-20 08:09:54 -05:00
Martin Fischer
ff6defc988 refactor: Introduce get_indent helper for scripts 2023-01-20 08:09:54 -05:00
Martin Fischer
67ca50e9f2 refactor: Reduce code duplication in scripts/ 2023-01-20 08:09:54 -05:00
Martin Fischer
6cc160bc2b Mark scripts/add_*.py as executable 2023-01-20 08:09:54 -05:00
Ville Skyttä
4bdf506d80 Grammar fixes (#2014) 2023-01-20 07:44:23 -05:00
Charlie Marsh
4af2353ef9 Avoid trimming docstring if ends in trailing quote (#2025)
Closes #2017.
2023-01-20 07:41:58 -05:00
Ville Skyttä
6072edf5bf Note .astimezone() in call-datetime-strptime-without-zone message (#2015) 2023-01-20 07:40:34 -05:00
Martin Fischer
4061eeeb32 Update CI to use MSRV for cargo test and build
As per Cargo.toml our minimal supported Rust version is 1.65.0, so we
should be using that version in our CI for cargo test and cargo build.

This was apparently accidentally changed in
79ca66ace5.
2023-01-20 07:39:40 -05:00
Aarni Koskela
bea6deb0c3 Port pydocstyle code 401 (ImperativeMood) (#1999)
This adds support for pydocstyle code D401 using the `imperative` crate.
2023-01-20 07:18:27 -05:00
Colin Delahunty
81db00a3c4 Pyupgrade: Extraneous parenthesis (#1926) 2023-01-20 00:04:07 -05:00
Charlie Marsh
cf56955ba6 Bump version to 0.0.227 2023-01-19 23:24:52 -05:00
Charlie Marsh
8a8939afd8 Avoid checking row types for single-name @parametrize decorators (#2013)
Closes #2008.
2023-01-19 22:13:17 -05:00
Martin Fischer
6acf2accc6 Improve --explain output
Previous output for `ruff --explain E711`:

    E711 (pycodestyle): Comparison to `None` should be `cond is None`

New output:

    none-comparison

    Code: E711 (pycodestyle)

    Autofix is always available.

    Message formats:

    * Comparison to `None` should be `cond is None`
    * Comparison to `None` should be `cond is not None`
2023-01-19 22:08:00 -05:00
Charlie Marsh
ec0c7647ab Avoid SIM401 in elif blocks (#2012)
For now, we're just gonna avoid flagging this for `elif` blocks, following the same reasoning as for ternaries. We can handle all of these cases, but we'll knock out the TODOs as a pair, and this avoids broken code.

Closes #2007.
2023-01-19 21:57:18 -05:00
Charlie Marsh
045229630e Upgrade RustPython (#2011)
This lets us revert the "manual" fix introduced in #1944.
2023-01-19 21:49:12 -05:00
Martin Fischer
c600991905 Change AsRef<str> impl for Rule to kebab-case
As we surface rule names more to users we want
them to be easier to type than PascalCase.

Prior art:

Pylint and ESLint also use kebab-case for their rule names.
Clippy uses snake_case but only for syntactical reasons
(so that the argument to e.g. #![allow(clippy::some_lint)]
can be parsed as a path[1]).

[1]: https://doc.rust-lang.org/reference/paths.html
2023-01-19 21:37:11 -05:00
Charlie Marsh
f6a93a4c3d Enable autofix for FitsOnOneLine (D200) (#2006)
Closes #1965.
2023-01-19 19:24:50 -05:00
Aarni Koskela
de54ff114e Add RUF005 "unpack instead of concatenating" check (#1957)
This PR adds a new check that turns expressions such as `[1, 2, 3] + foo` into `[1, 2, 3, *foo]`, since the latter is easier to read and faster:

```
~ $ python3.11 -m timeit -s 'b = [6, 5, 4]' '[1, 2, 3] + b'
5000000 loops, best of 5: 81.4 nsec per loop
~ $ python3.11 -m timeit -s 'b = [6, 5, 4]' '[1, 2, 3, *b]'
5000000 loops, best of 5: 66.2 nsec per loop
```

However there's a couple of gotchas:

* This felt like a `simplify` rule, so I borrowed an unused `SIM` code even if the upstream `flake8-simplify` doesn't do this transform. If it should be assigned some other code, let me know 😄 
* **More importantly** this transform could be unsafe if the other operand of the `+` operation has overridden `__add__` to do something else. What's the `ruff` policy around potentially unsafe operations? (I think some of the suggestions other ported rules give could be semantically different from the original code, but I'm not sure.)
* I'm not a very established Rustacean, so there's no doubt my code isn't quite idiomatic. (For instance, is there a neater way to write that four-way `match` statement?)

Thanks for `ruff`, by the way! :)
2023-01-19 17:38:17 -05:00
Charlie Marsh
64b398c72b Tweak some instructions in CONTRIBUTING.md 2023-01-19 17:17:39 -05:00
Aarni Koskela
c99bd3fa60 Split up pydocstyle rules (#2003)
As per @not-mAs per @not-my-profile's [comment](https://github.com/charliermarsh/ruff/pull/1999#discussion_r1081579337):

> we actually want to break up such rules.rs files into smaller files

this breaks up `pydocstyle/rules.rs` into a directory.y-profile's [comment](https://github.com/charliermarsh/ruff/pull/1999#discussion_r1081579337):

> we actually want to break up such rules.rs files into smaller files

this breaks up `pydocstyle/rules.rs` into a directory.
2023-01-19 13:17:25 -05:00
Martin Fischer
8ac930f886 Fix that --explain panics
This commit fixes a bug accidentally introduced in
6cf770a692,
which resulted every `ruff --explain <code>` invocation to fail with:

    thread 'main' panicked at 'Mismatch between definition and access of `explain`.
    Could not downcast to ruff::registry::Rule, need to downcast to &ruff::registry::Rule',
    ruff_cli/src/cli.rs:184:18

We also add an integration test for --explain to prevent such bugs from
going by unnoticed in the future.
2023-01-19 12:58:44 -05:00
Charlie Marsh
ad80fdc2cd Avoid SIM201 and SIM202 errors in __ne__ et al (#2001)
Closes #1986.
2023-01-19 11:27:27 -05:00
Aarni Koskela
a0ea8fe22f Apply #[derive(Default)] fixes suggested by Clippy (#2000)
These were bugging me every time I ran `clippy` 😁
2023-01-19 11:04:43 -05:00
Martin Fischer
3c3da8a88c derive-msg-formats 5/5: Remove placeholder implementations
# This commit has been generated via the following Python script:
# (followed by `cargo +nightly fmt` and `cargo dev generate-all`)
# For the reasoning see the previous commit(s).

import re
import sys

for path in (
    'src/violations.rs',
    'src/rules/flake8_tidy_imports/banned_api.rs',
    'src/rules/flake8_tidy_imports/relative_imports.rs',
):
    with open(path) as f:
        text = ''

        while line := next(f, None):

            if line.strip() != 'fn message(&self) -> String {':
                text += line
                continue

            text += '    #[derive_message_formats]\n' + line

            body = next(f)
            while (line := next(f)) != '    }\n':
                body += line

            # body = re.sub(r'(?<!code\| |\.push\()format!', 'format!', body)
            body = re.sub(
                r'("[^"]+")\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL
            )
            body = re.sub(
                r'(r#".+?"#)\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL
            )

            text += body + '    }\n'

            while (line := next(f)).strip() != 'fn placeholder() -> Self {':
                text += line
            while (line := next(f)) != '    }\n':
                pass

    with open(path, 'w') as f:
        f.write(text)
2023-01-19 11:03:32 -05:00
Martin Fischer
16e79c8db6 derive-msg-formats 4/5: Implement #[derive_message_formats]
The idea is nice and simple we replace:

    fn placeholder() -> Self;

with

    fn message_formats() -> &'static [&'static str];

So e.g. if a Violation implementation defines:

    fn message(&self) -> String {
        format!("Local variable `{name}` is assigned to but never used")
    }

it would also have to define:

   fn message_formats() -> &'static [&'static str] {
       &["Local variable `{name}` is assigned to but never used"]
   }

Since we however obviously do not want to duplicate all of our format
strings we simply introduce a new procedural macro attribute
#[derive_message_formats] that can be added to the message method
declaration in order to automatically derive the message_formats
implementation.

This commit implements the macro. The following and final commit
updates violations.rs to use the macro. (The changes have been separated
because the next commit is autogenerated via a Python script.)
2023-01-19 11:03:32 -05:00
Martin Fischer
8f6d8e215c derive-msg-formats 3/5: Introduce Violation::AUTOFIX associated constant
ruff_dev::generate_rules_table previously documented which rules are
autofixable via DiagnosticKind::fixable ... since the DiagnosticKind was
obtained via Rule::kind (and Violation::placeholder) which we both want
to get rid of we have to obtain the autofixability via another way.

This commit implements such another way by adding an AUTOFIX
associated constant to the Violation trait. The constant is of the type
Option<AutoFixkind>, AutofixKind is a new struct containing an
Availability enum { Sometimes, Always}, letting us additionally document
that some autofixes are only available sometimes (which previously
wasn't documented). We intentionally introduce this information in a
struct so that we can easily introduce further autofix metadata in the
future such as autofix applicability[1].

[1]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_errors/enum.Applicability.html
2023-01-19 11:03:32 -05:00
Martin Fischer
8993baab01 derive-msg-formats 2/5: Remove DiagnosticKind::summary
While ruff displays the string returned by Violation::message in its
output for detected violations the messages displayed in the README
and in the `--explain <code>` output previously used the
DiagnosticKind::summary() function which for some verbose messages
provided shorter descriptions.

This commit removes DiagnosticKind::summary, and moves the more
extensive documentation into doc comments ... these are not displayed
yet to the user but doing that is very much planned.
2023-01-19 11:03:32 -05:00
Martin Fischer
2568627c4c derive-msg-formats 1/5: Remove unnecessary usages of Rule::kind
This commit series removes the following associated
function from the Violation trait:

    fn placeholder() -> Self;

ruff previously used this placeholder approach for the messages it
listed in the README and displayed when invoked with --explain <code>.

This approach is suboptimal for three reasons:

1. The placeholder implementations are completely boring code since they
   just initialize the struct with some dummy values.

2. Displaying concrete error messages with arbitrary interpolated values
   can be confusing for the user since they might not recognize that the
   values are interpolated.

3. Some violations have varying format strings depending on the
   violation which could not be documented with the previous approach
   (while we could have changed the signature to return Vec<Self> this
   would still very much suffer from the previous two points).

We therefore drop Violation::placeholder in favor of a new macro-based
approach, explained in commit 4/5.

Violation::placeholder is only invoked via Rule::kind, so we firstly
have to get rid of all Rule::kind invocations ... this commit starts
removing the trivial cases.
2023-01-19 11:03:32 -05:00
Martin Fischer
9603a024b3 refactor: Move a bunch of pandas-vet logic to rules::pandas_vet 2023-01-19 11:03:32 -05:00
Charlie Marsh
a122d95ef5 Preserve unmatched comparators in SIM109 (#1998)
Closes #1993.
2023-01-19 10:23:20 -05:00
Damien Allen
6ddfe50ac4 Added pylint formatter (#1995)
Fixes: #1953

@charliermarsh thank you for the tips in the issue.

I'm not very familiar with Rust, so please excuse if my string formatting syntax is messy.

In terms of testing, I compared output of `flake8 --format=pylint ` and `cargo run --format=pylint` on the same code and the output syntax seems to check out.
2023-01-19 08:01:27 -05:00
Martin Fischer
26901a78c9 Make define_rule_mapping! set rule code as doc comment of variants
Since the UI still relies on the rule codes this improves the developer
experience by letting developers view the code of a Rule enum variant by
hovering over it.
2023-01-19 07:37:16 -05:00
Martin Fischer
6649225167 rule 8/8: Automatically rewrite RuleCode to Rule
# This commit was automatically generated by running the following
# script (followed by `cargo +nightly fmt`):

import glob
import re
from typing import NamedTuple

class Rule(NamedTuple):
    code: str
    name: str
    path: str

def rules() -> list[Rule]:
    """Returns all the rules defined in `src/registry.rs`."""
    file = open('src/registry.rs')

    rules = []

    while next(file) != 'ruff_macros::define_rule_mapping!(\n':
        continue

    while (line := next(file)) != ');\n':
        line = line.strip().rstrip(',')
        if line.startswith('//'):
            continue
        code, path = line.split(' => ')
        name = path.rsplit('::')[-1]
        rules.append(Rule(code, name, path))

    return rules

code2name = {r.code: r.name for r in rules()}

for pattern in ('src/**/*.rs', 'ruff_cli/**/*.rs', 'ruff_dev/**/*.rs', 'scripts/add_*.py'):
    for name in glob.glob(pattern, recursive=True):
        with open(name) as f:
            text = f.read()

        text = re.sub('Rule(?:Code)?::([A-Z]\w+)', lambda m: 'Rule::' + code2name[m.group(1)], text)
        text = re.sub(r'(?<!"<FilePattern>:<)RuleCode\b', 'Rule', text)
        text = re.sub('(use crate::registry::{.*, Rule), Rule(.*)', r'\1\2', text) # fix duplicate import

        with open(name, 'w') as f:
            f.write(text)
2023-01-18 23:51:48 -05:00
Martin Fischer
9e3083aa2c rule 7/8: Change Rule enum definition 2023-01-18 23:51:48 -05:00
Martin Fischer
6d11ff3822 rule 6/8: Remove Serialize & Deserialize impls for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
6cf770a692 rule 5/8: Remove FromStr impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3534e370e1 rule 4/8: Remove Display impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
dbcab5128c rule 3/8: Remove AsRef<str> impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3810250bb6 rule 2/8: Rename DiagnosticKind::code to rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3c1c1e1dd3 rule 1/8: Rename RuleCode to Rule (backwards-compatible for now)
This commit series refactors ruff to decouple "rules" from "rule codes",
in order to:

1. Make our code more readable by changing e.g.
   RuleCode::UP004 to Rule::UselessObjectInheritance.

2. Let us cleanly map multiple codes to one rule, for example:

   [UP004] in pyupgrade, [R0205] in pylint and [PIE792] in flake8-pie
   all refer to the rule UselessObjectInheritance but ruff currently
   only associates that rule with the UP004 code (since the
   implementation was initially modeled after pyupgrade).

3. Let us cleanly map one code to multiple rules, for example:

   [C0103] from pylint encompasses N801, N802 and N803 from pep8-naming.

The latter two steps are not yet implemented by this commit series
but this refactoring enables us to introduce such a mapping.  Such a
mapping would also let us expand flake8_to_ruff to support e.g. pylint.

After the next commit which just does some renaming the following four
commits remove all trait derivations from the Rule (previously RuleCode)
enum that depend on the variant names to guarantee that they are not
used anywhere anymore so that we can rename all of these variants in the
eigth and final commit without breaking anything.

While the plan very much is to also surface these human-friendly names
more in the user interface this is not yet done in this commit series,
which does not change anything about the UI: it's purely a refactor.

[UP004]: pyupgrade doesn't actually assign codes to its messages.
[R0205]: https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/useless-object-inheritance.html
[PIE792]: https://github.com/sbdchd/flake8-pie#pie792-no-inherit-object
[C0103]: https://pylint.pycqa.org/en/latest/user_guide/messages/convention/invalid-name.html
2023-01-18 23:51:48 -05:00
Martin Fischer
5b7bd93b91 refactor: Use Self:: in match arms 2023-01-18 23:51:48 -05:00
Martin Fischer
9e096b4a4c refactor: Make define_rule_mapping! generate RuleCodePrefix directly 2023-01-18 23:51:48 -05:00
Charlie Marsh
d8645acd1f Bump version to 0.0.226 2023-01-18 20:54:38 -05:00
Charlie Marsh
92dd073191 Add Pylint settings to lib_wasm.rs 2023-01-18 20:54:03 -05:00
Charlie Marsh
ff96219e62 Exclude None, Bool, and Ellipsis from ConstantType (#1988)
These have no effect, so it's confusing that they're even settable.
2023-01-18 20:50:09 -05:00
Charlie Marsh
d33424ec9d Enable suppression of magic values by type (#1987)
Closes #1949.
2023-01-18 20:44:24 -05:00
Charlie Marsh
34412a0a01 Avoid removing side effects for boolean simplifications (#1984)
Closes #1978.
2023-01-18 19:08:14 -05:00
Charlie Marsh
ceb48d3a32 Use relative paths for INP001 (#1981) 2023-01-18 18:45:47 -05:00
Charlie Marsh
969a6f0d53 Replace misplaced-comparison-constant with SIM300 (#1980)
Closes: #1954.
2023-01-18 18:42:49 -05:00
Charlie Marsh
7628876ff2 Invert order of yoda-conditions message (#1979)
The suggestion was wrong!
2023-01-18 18:27:36 -05:00
Charlie Marsh
ef355e5c2c Remove artificial wraps from GitHub messages (#1977) 2023-01-18 18:20:56 -05:00
Charlie Marsh
97f55b8e97 Convert remaining call path sites to use SmallVec (#1972) 2023-01-18 14:50:33 -05:00
Aarni Koskela
ff2be35f51 Run cargo fmt in pre-commit (#1968)
Since `cargo fmt` is a required CI check, we could just as well run it in `pre-commit`.
2023-01-18 13:14:51 -05:00
Anders Kaseorg
1e803f7108 README: Link “Flake8” for consistency with the rest of the list (#1969)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 13:07:21 -05:00
Charlie Marsh
1ab0273aa7 Strip whitespace when injecting D209 newline (#1967)
Closes #1963.
2023-01-18 12:09:17 -05:00
Charlie Marsh
5a7d8c25f4 Treat subscript accesses as unsafe effects for autofix (#1966)
See: #1809.
2023-01-18 11:46:12 -05:00
Charlie Marsh
26d6414558 Fix UP003 check from rebase 2023-01-18 11:39:39 -05:00
Charlie Marsh
dae95626ae Use smallvec for call path representation (#1960)
This provides a ~10% speed-up for large codebases with `--select ALL`:

![Screen Shot 2023-01-18 at 11 28 20 AM](https://user-images.githubusercontent.com/1309177/213236389-cff50840-6e55-47a3-9164-2e40cbc885f6.png)
2023-01-18 11:29:05 -05:00
Maksudul Haque
9a3e525930 [isort] Add no-lines-before Option (#1955)
Closes https://github.com/charliermarsh/ruff/issues/1916.
2023-01-18 11:09:47 -05:00
Anders Kaseorg
b9c6cfc0ab Autofix SIM117 (MultipleWithStatements) (#1961)
This is slightly buggy due to Instagram/LibCST#855; it will complain `[ERROR] Failed to fix nested with: Failed to extract CST from source` when trying to fix nested parenthesized `with` statements lacking trailing commas. But presumably people who write parenthesized `with` statements already knew that they don’t need to nest them.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 11:06:04 -05:00
Charlie Marsh
b1f10c8339 Confine type-of-primitive checks to builtin type calls (#1962)
Closes #1958.
2023-01-18 10:53:50 -05:00
Anders Kaseorg
83346de6e0 Autofix SIM102 (NestedIfStatements)
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
b23cc31863 Change ast::helpers::has_coments to accept a Range
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
462d81beb7 Ensure ast::whitespace::indentation extracts whitespace
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
715ea2d374 Accept a Locator for ast::whitespace::indentation
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
skykasko
6c7e60b4f9 Fix bad link for flake8-no-pep420 (#1952)
See https://github.com/charliermarsh/ruff/pull/1942.
2023-01-18 07:36:05 -05:00
Maksudul Haque
868d0b3e29 [isort] Add constants and variables Options (#1951)
closes https://github.com/charliermarsh/ruff/issues/1819
2023-01-18 07:30:51 -05:00
Charlie Marsh
cdb4700813 Bump version to 0.0.225 2023-01-18 00:22:48 -05:00
Anders Kaseorg
ea4d54a90f Restrict SIM105 to try blocks with a body of one simple statement (#1948)
If a `try` block has multiple statements, a compound statement, or
control flow, rewriting it with `contextlib.suppress` would obfuscate
the fact that the exception still short-circuits further statements in
the block.

Fixes #1947.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 00:22:22 -05:00
Charlie Marsh
51b917cfbf Exempt contextlib.ExitStack() for SIM115 rules (#1946)
Since our binding tracking is somewhat limited, I opted to favor false negatives over false positives. So, e.g., this won't trigger SIM115:

```py
with contextlib.ExitStack():
    f = exit_stack.enter_context(open("filename"))
```

(Notice that `exit_stack` is unbound.)

The alternative strategy required us to incorrectly trigger SIM115 on this:

```py
with contextlib.ExitStack() as exit_stack:
    exit_stack_ = exit_stack
    f = exit_stack_.enter_context(open("filename"))
```

Closes #1945.
2023-01-17 22:39:54 -05:00
Edgar R. M
c880d744fd Implement flake8-no-pep420 (#1942)
Closes https://github.com/charliermarsh/ruff/issues/1844.
2023-01-17 22:10:32 -05:00
Charlie Marsh
84d1df08be Avoid broken autofix for SIM103 with elif (#1944)
Also adjusts the generator to avoid the extra parentheses (and skips commented `if` statements).

Closes #1943.
2023-01-17 22:03:17 -05:00
Charlie Marsh
b9bb5acff8 Remove unnecessary setuptools block 2023-01-17 21:17:37 -05:00
Charlie Marsh
ca7c3c2175 Avoid autofixing comma rules when --fix is not set (#1940)
Closes #1939.
2023-01-17 20:09:01 -05:00
Charlie Marsh
8891e2e62b Fix name of ruff-pre-commit event 2023-01-17 17:25:02 -05:00
Martin Fischer
53265e0ed4 cli: Catch panics to tell the user to report them (#1928) 2023-01-17 17:17:09 -05:00
Charlie Marsh
072849a8a9 Move @functools.cache rewrites to their own rule (#1938)
Closes #1934.
2023-01-17 15:12:40 -05:00
Charlie Marsh
70ea4b25e8 Allow duplicate enum values for enum.auto() (#1933)
Closes #1932.
2023-01-17 11:14:11 -05:00
Martin Fischer
30e133f3d8 refactor: Declare defaults once in settings::defaults 2023-01-17 09:20:57 -05:00
Martin Fischer
aa812de07e refactor: Implement Default for Settings 2023-01-17 09:20:57 -05:00
Martin Fischer
57ac6a8444 refactor: Make resolve_codes take IntoIterator instead of Iterator 2023-01-17 09:20:57 -05:00
Martin Fischer
a6566b1b34 refactor: Merge Settings.enabled and Settings.fixable
The Settings struct previously contained the fields:

     pub enabled: HashableHashSet<RuleCode>,
     pub fixable: HashableHashSet<RuleCode>,

This commit merges both fields into one by introducing a new
RuleTable type, wrapping HashableHashMap<RuleCode, bool>,
which has the following benefits:

1. It makes the invalid state that a rule is
   disabled but fixable unrepresentable.

2. It encapsulates the implementation details of the table.
   (It currently uses an FxHashMap but that may change.)

3. It results in more readable code.

       settings.rules.enabled(rule)
       settings.rules.should_fix(rule)

   is more readable than:

       settings.enabled.contains(rule)
       settings.fixable.contains(rule)
2023-01-17 09:20:57 -05:00
Martin Fischer
580da1fa6b refactor: Group Settings fields 2023-01-17 09:20:57 -05:00
Martin Fischer
b78b6f275e refactor: Define origin names & URLs within doc comments 2023-01-17 07:44:40 -05:00
Martin Fischer
6868bb46f5 refactor: Get rid of Platform enum 2023-01-17 07:44:40 -05:00
Martin Fischer
601848d9a8 refactor: Rename RuleOrigin::title to RuleOrigin::name 2023-01-17 07:44:40 -05:00
Martin Fischer
f4da7635f0 Add missing url for flake8-import-conventions 2023-01-17 07:44:40 -05:00
Charlie Marsh
74a8a218f3 Bump version to 0.0.224 2023-01-16 23:43:14 -05:00
Colin Delahunty
1730f2a603 [pyupgrade] Automatically rewrite format-strings to f-strings (#1905) 2023-01-16 23:06:39 -05:00
Charlie Marsh
a4862857de Update PIE796 fixture 2023-01-16 19:29:14 -05:00
Leonardo Esparis
6e88c60c46 Add flake8-pie PIE796: prefer-unique-enum (#1923)
I accept any suggestion. By the way, I have a doubt, I have checked and all flake8-pie plugins can be fixed by ruff, but is it necessary that this one is also fixed automatically ?

rel #1543
2023-01-16 19:27:34 -05:00
Charlie Marsh
2ed1f78873 Add benchmark scripts for no-IO (#1925) 2023-01-16 17:38:40 -05:00
Charlie Marsh
f3bf008aed Avoid removing statements that contain side-effects (#1920)
Closes #1917.
2023-01-16 14:45:02 -05:00
Charlie Marsh
3b4aaa53c1 Add some new testimonials (#1921) 2023-01-16 14:44:52 -05:00
Charlie Marsh
6abf71639f Avoid syntax errors when fixing parenthesized unused variables (#1919)
Closes #1917.
2023-01-16 14:27:41 -05:00
Charlie Marsh
c0845a8c28 Rewrite lru_cache to cache on Python 3.9+ (#1918)
Closes #1913.
2023-01-16 13:14:27 -05:00
Paul Barrett
019ecc4add Trigger update to pre-commit mirror after pypi publish (#1910) 2023-01-16 13:14:18 -05:00
Martin Fischer
f4cf48d885 refactor: Move rule-specific details out of mod.rs via type aliases 2023-01-16 11:27:24 -05:00
Martin Fischer
005f5d7911 refactor: Make flake8_tidy_imports::Settings derive Default 2023-01-16 11:27:24 -05:00
Martin Fischer
2fce580693 refactor: Move flake8_tidy_imports Settings to mod.rs 2023-01-16 11:27:24 -05:00
Martin Fischer
8862565a0f refactor: Split ruff::rules::flake8_tidy_imports::rules 2023-01-16 11:27:24 -05:00
Martin Fischer
5bf6da0db7 refactor: Rename BannedRelativeImport to RelativeImports
The idea is to follow the Rust naming convention for lints[1]:

> the lint name should make sense when read as
> "allow lint-name" or "allow lint-name items"

Following that convention prefixing "Banned" is
redundant as it could be prefixed to any lint name.

[1]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
2023-01-16 11:27:24 -05:00
Martin Fischer
ee655c1a88 refactor: Rename BannedApi to ApiBan to distinguish it from the violation struct 2023-01-16 11:27:24 -05:00
Harutaka Kawamura
2236b4bd59 Add backticks to B904's message (#1914)
This PR adds backticks to B904's message to improve readability.


Without backticks:

<img width="1480" alt="image" src="https://user-images.githubusercontent.com/17039389/212682457-71f13de9-e3dd-4ead-a82b-98e5b60653c2.png">

With backticks:

<img width="1480" alt="image" src="https://user-images.githubusercontent.com/17039389/212682775-36868401-b63e-47d1-ae25-b43b61866b6c.png">
2023-01-16 11:12:43 -05:00
Charlie Marsh
fbf311f7d5 Add instructions for Pyupgrade benchmark 2023-01-16 03:21:31 -05:00
Martin Fischer
8c18b28bc4 Derive Hash instead of implementing it by hand
The caching mechanism of the CLI (ruff_cli::cache) relies on
ruff::settings::Settings implementing the Hash trait.

The ruff::settings::Settings struct previously couldn't automatically
derive the Hash implementation via the #[derive(Hash)] macro attribute
since some of its field types intentionally[1][2] don't implement Hash
(namely regex::Regex, globset::GlobMatcher and globset::GlobSet and
HashMap and HashSet from the standard library).

The code therefore previously implemented the Hash trait by hand for the
whole struct. Implementing Hash by hand for structs that are subject to
change is a bad idea since it's very easy to forget to update the Hash
implementation when adding a new field to the struct. And the Hash
implementation indeed was already incorrect by omitting several fields
from the hash.

This commit introduces wrapper types for Regex, GlobMatcher, GlobSet,
HashSet & HashMap that implement Hash so that we can still add
#[derive(Hash)] to the Settings struct, guaranteeing a correct hash
implementation.

[1]: https://github.com/rust-lang/regex/issues/364#issuecomment-301082076
[2]: The standard library doesn't impl<T: Hash + Ord> Hash for HashSet<T>
     presumably since sorted() requires an allocation and Hash
     implementations are generally expected to work without allocations.
2023-01-16 01:42:55 -05:00
Charlie Marsh
42031b8574 Re-run benchmark and update documentation (#1907)
Closes #269.
2023-01-16 01:38:58 -05:00
Charlie Marsh
3a3a5fcd81 Remove -dev suffix from flake8_to_ruff 2023-01-15 22:45:14 -05:00
Charlie Marsh
e8577d5e26 Bump version to 0.0.223 2023-01-15 22:44:01 -05:00
Charlie Marsh
bcb1e6ba20 Add flake8-commas to the README 2023-01-15 22:43:29 -05:00
Charlie Marsh
15403522c1 Avoid triggering SIM117 for async with statements (#1903)
Actually, it looks like _none_ of the existing rules should be triggered on async `with` statements.

Closes #1902.
2023-01-15 21:42:36 -05:00
messense
cb4f305ced Lock stdout once when printing diagnostics (#1901)
https://doc.rust-lang.org/stable/std/io/struct.Stdout.html

> Each handle shares a global buffer of data to be written to the standard output stream.
> Access is also synchronized via a lock and
> explicit control over locking is available via the [`lock`](https://doc.rust-lang.org/stable/std/io/struct.Stdout.html#method.lock) method.
2023-01-15 21:04:00 -05:00
Charlie Marsh
d71a615b18 Buffer diagnostic writes to stdout (#1900) 2023-01-15 19:34:15 -05:00
Charlie Marsh
dfc2a34878 Remove rogue println 2023-01-15 18:59:59 -05:00
Charlie Marsh
7608087776 Don't require docstrings for setters and deleters (#1899) 2023-01-15 18:57:38 -05:00
Charlie Marsh
228f033e15 Skip noqa checker if no diagnostics are found (#1898) 2023-01-15 18:53:00 -05:00
Martin Fischer
d75d6d7c7c refactor: Split CliSettings from Settings
We want to automatically derive Hash for the library settings, which
requires us to split off all the settings unused by the library
(since these shouldn't affect the hash used by ruff_cli::cache).
2023-01-15 15:19:42 -05:00
Martin Fischer
ef80ab205c Mark Settings::for_rule(s) as test-only 2023-01-15 15:19:42 -05:00
Ran Benita
d3041587ad Implement flake8-commas (#1872)
Implements [flake8-commas](https://github.com/PyCQA/flake8-commas). Fixes #1058.

The plugin is mostly redundant with Black (and also deprecated upstream), but very useful for projects which can't/won't use an auto-formatter. 

This linter works on tokens. Before porting to Rust, I cleaned up the Python code ([link](https://gist.github.com/bluetech/7c5dcbdec4a73dd5a74d4bc09c72b8b9)) and made sure the tests pass. In the Rust version I tried to add explanatory comments, to the best of my understanding of the original logic.

Some changes I did make:

- Got rid of rule C814 - "missing trailing comma in Python 2". Ruff doesn't support Python 2.
- Merged rules C815 - "missing trailing comma in Python 3.5+" and C816 - "missing trailing comma in Python 3.6+" into C812 - "missing trailing comma". These Python versions are outdated, didn't think it was worth the complication.
- Added autofixes for C812 and C819.

Autofix is missing for C818 - "trailing comma on bare tuple prohibited". It needs to turn e.g. `x = 1,` into `x = (1, )`, it's a bit difficult to do with tokens only, so I skipped it for now.

I ran the rules on cpython/Lib and on a big internal code base and it works as intended (though I only sampled the diffs).
2023-01-15 14:03:32 -05:00
Harutaka Kawamura
8d912404b7 Use more precise error ranges for RET505~508 (#1895) 2023-01-15 13:54:24 -05:00
Tom Fryers
85bdb45eca Improve magic value message wording (#1892)
The message previously specified 'number', but the error applies to more types.
2023-01-15 12:53:02 -05:00
messense
c7d0d26981 Update add plugin/rule scripts (#1889)
Adjusted some file locations and changed to use [`pathlib`](https://docs.python.org/3/library/pathlib.html) instead of `os.path`.
2023-01-15 12:49:42 -05:00
Charlie Marsh
5c6753e69e Remove some Clippy allows (#1888) 2023-01-15 02:32:36 -05:00
Charlie Marsh
3791ca721a Add a dedicated token indexer for continuations and comments (#1886)
The primary motivation is that we can now robustly detect `\` continuations due to the addition of `Tok::NonLogicalNewline`. This PR generalizes the approach we took to comments (track all lines that contain any comments), and applies it to continuations too.
2023-01-15 01:57:31 -05:00
Charlie Marsh
2c644619e0 Convert confusable violations to named fields (#1887)
See: #1871.
2023-01-15 01:56:18 -05:00
Martin Fischer
81996f1bcc Convert define_rule_mapping! to a procedural macro
define_rule_mapping! was previously implemented as a declarative macro,
which was however partially relying on an origin_by_code! proc macro
because declarative macros cannot match on substrings of identifiers.

Currently all define_rule_mapping! lines look like the following:

    TID251 => violations::BannedApi,
    TID252 => violations::BannedRelativeImport,

We want to break up violations.rs, moving the violation definitions to
the respective rule modules. To do this we want to change the previous
lines to:

    TID251 => rules::flake8_tidy_imports::banned_api::BannedApi,
    TID252 => rules::flake8_tidy_imports::relative_imports::RelativeImport,

This however doesn't work because the define_rule_mapping! macro is
currently defined as:

    ($($code:ident => $mod:ident::$name:ident,)+) => { ... }

That is it only supported $module::$name but not longer paths with
multiple modules. While we could define `=> $path:path`[1] then we
could no longer access the last path segment, which we need because
we use it for the DiagnosticKind variant names. And
`$path:path::$last:ident` doesn't work either because it would be
ambiguous (Rust wouldn't know where the path ends ... so path fragments
have to be followed by some punctuation/keyword that may not be part of
paths). And we also cannot just introduce a procedural macro like
path_basename!(...) because the following is not valid Rust code:

    enum Foo { foo!(...), }

(macros cannot be called in the place where you define variants.)

So we have to convert define_rule_mapping! into a proc macro in order to
support paths of arbitrary length and this commit implements that.

[1]: https://doc.rust-lang.org/reference/macros-by-example.html#metavariables
2023-01-15 01:54:57 -05:00
Charlie Marsh
e3cc918b93 Bump version to 0.0.222 2023-01-14 23:34:53 -05:00
Charlie Marsh
d864477876 Turn doc references into links (#1878) 2023-01-14 23:27:45 -05:00
Charlie Marsh
e1ced89624 Document breaking --max-complexity change 2023-01-14 23:22:38 -05:00
Martin Fischer
4470d7ba04 Make the CI check for broken links in the Rust docs (#1883) 2023-01-14 23:18:17 -05:00
Harutaka Kawamura
2a1601749f Fix range of SIM201, 202, and 208 (#1880)
Before

```
resources/test/fixtures/flake8_simplify/SIM208.py:1:13: SIM208 Use `a` instead of `not (not a)`
  |
1 | if not (not a):  # SIM208
  |             ^ SIM208
  |
  = help: Replace with `a`

resources/test/fixtures/flake8_simplify/SIM208.py:4:14: SIM208 Use `a == b` instead of `not (not a == b)`
  |
4 | if not (not (a == b)):  # SIM208
  |              ^^^^^^ SIM208
  |
  = help: Replace with `a == b`
```

After

```
resources/test/fixtures/flake8_simplify/SIM208.py:1:4: SIM208 Use `a` instead of `not (not a)`
  |
1 | if not (not a):  # SIM208
  |    ^^^^^^^^^^^ SIM208
  |
  = help: Replace with `a`

resources/test/fixtures/flake8_simplify/SIM208.py:4:4: SIM208 Use `a == b` instead of `not (not a == b)`
  |
4 | if not (not (a == b)):  # SIM208
  |    ^^^^^^^^^^^^^^^^^^ SIM208
  |
  = help: Replace with `a == b`
```
2023-01-14 21:17:32 -05:00
Charlie Marsh
a01edad1c4 Remove --max-complexity from the CLI (#1877) 2023-01-14 18:27:23 -05:00
Martin Fischer
a81ac6705d Make ruff::source_code::{Generator, Locator, Stylist} private 2023-01-14 18:23:59 -05:00
Martin Fischer
d77675f30d Make ruff::{ast, autofix, directives, rustpython_helpers} private 2023-01-14 18:23:59 -05:00
Martin Fischer
fe7658199d Make ruff::violations private 2023-01-14 18:23:59 -05:00
Martin Fischer
cfa25ea4b0 Make ruff::rules private 2023-01-14 18:23:59 -05:00
Martin Fischer
c7f0f3b237 Regenerate insta snapshots 2023-01-14 11:48:02 -05:00
Martin Fischer
3b36030461 Introduce ruff::rules module
Resolves #1547.
2023-01-14 11:48:02 -05:00
Charlie Marsh
812df77246 Add Dagster and SnowCLI 2023-01-14 10:45:16 -05:00
Martin Fischer
69b356e9b9 Add top-level doc comments for crates
Test by running:

    cargo doc --no-deps --all --open
2023-01-14 10:11:30 -05:00
Martin Fischer
033d7d7e91 Disable doc generation for the ruff_cli binary 2023-01-14 10:11:30 -05:00
Martin Fischer
a181ca7a3d Reduce the API of ruff_cli to ruff_cli::help() 2023-01-14 10:11:30 -05:00
Martin Fischer
92124001d5 Turn ruff_dev into a bin-only crate 2023-01-14 10:11:30 -05:00
Martin Fischer
06b389c5bc Turn flake8_to_ruff into a bin-only crate 2023-01-14 10:11:30 -05:00
Thomas MK
9dc66b5a65 Split up the table corresponding to the pylint rules (#1868)
This makes it easier to see which rules you're enabling when selecting
one of the pylint codes (like `PLC`). This also makes it clearer what
those abbreviations stand for. When I first saw the pylint section, I
was very confused by that, so other might be as well.

See it rendered here:
https://github.com/thomkeh/ruff/blob/patch-1/README.md#pylint-plc-ple-plr-plw
2023-01-14 08:07:02 -05:00
Ran Benita
3447dd3615 Bump RustPython (#1836)
This bumps RustPython so we can use the new `NonLogicalNewline` token.
A couple of rules needed a fix due to the new token. There might be more
that are not caught by tests (anything working with tokens directly with
lookaheads), I hope not.
2023-01-14 08:03:27 -05:00
Harutaka Kawamura
42cb106377 Improve SIM117 (#1867)
This PR makes the following changes to improve `SIM117`:

- Avoid emitting `SIM117` multiple times within the same `with`
statement:
- Adjust the error range.  


## Example

```python
with A() as a:  # SIM117
    with B() as b:
        with C() as c:
            print("hello")
```

### Current

```
resources/test/fixtures/flake8_simplify/SIM117.py:5:1: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
5 | / with A() as a:  # SIM117
6 | |     with B() as b:
7 | |         with C() as c:
8 | |             print("hello")
  | |__________________________^ SIM117
  |

resources/test/fixtures/flake8_simplify/SIM117.py:6:5: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
6 |       with B() as b:
  |  _____^
7 | |         with C() as c:
8 | |             print("hello")
  | |__________________________^ SIM117
  |
```

### Improved

```
resources/test/fixtures/flake8_simplify/SIM117.py:5:1: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
5 | / with A() as a:  # SIM117
6 | |     with B() as b:
7 | |         with C() as c:
  | |______________________^ SIM117
  |
```

Signed-off-by: harupy <hkawamura0130@gmail.com>
2023-01-14 07:59:24 -05:00
Charlie Marsh
027382f891 Add support for namespace packages (#1859)
Closes #1817.
2023-01-14 07:31:57 -05:00
Charlie Marsh
931d41bff1 Revert "Bump version to 0.0.222"
This reverts commit 852aab5758.
2023-01-13 23:56:29 -05:00
Charlie Marsh
852aab5758 Bump version to 0.0.222 2023-01-13 23:50:08 -05:00
Charlie Marsh
27fe4873f2 Fix placement of update feature flag 2023-01-13 23:46:32 -05:00
Charlie Marsh
ee6c81d02a Bump version to 0.0.221 2023-01-13 23:33:15 -05:00
Charlie Marsh
59542344e2 Avoid unnecessary allocations for module names (#1863) 2023-01-13 23:26:34 -05:00
Martin Fischer
7b1ce72f86 Actually fix wasm-pack build command (#1862)
I initially attempted to run `wasm-pack build -p ruff` which gave the
error message:

Error: crate directory is missing a `Cargo.toml` file; is `-p` the wrong
directory?

I interpreted that as wasm-pack looking for the "ruff" directory because
I specified -p ruff, however actually the wasm-pack build usage is:

    wasm-pack build [FLAGS] [OPTIONS] <path> <cargo-build-options>

And I was missing the `<path>` argument. So this actually wasn't at all
a bug in wasm-pack but just a confusing error message. And the symlink
hack I introduced in the previous commit didn't actually work ... I only
accidentally omitted the `-p` when testing (which ended up as `ruff`
being the <path> argument) ... CLIs are fun.
2023-01-13 23:20:20 -05:00
Martin Fischer
156e09536e Add workaround for wasm-pack bug to fix the playground CI (#1861)
Fixes #1860.
2023-01-13 22:46:51 -05:00
Charlie Marsh
22341c4ae4 Move repology down 2023-01-13 22:29:26 -05:00
Colin Delahunty
e4993bd7e2 Added ALE (#1857)
Fixes the sub issue I brought up in #1829.
2023-01-13 21:39:51 -05:00
Martin Fischer
82aff5f9ec Split off ruff_cli crate from ruff library
This lets you test the ruff linters or use the ruff library
without having to compile the ~100 additional dependencies
that are needed by the CLI.

Because we set the following in the [workspace] section of Cargo.toml:

   default-members = [".", "ruff_cli"]

`cargo run` still runs the CLI and `cargo test` still tests
the code in src/ as well as the code in the new ruff_cli crate.
(But you can now also run `cargo test -p ruff` to only test the linters.)
2023-01-13 21:37:54 -05:00
Charlie Marsh
403a004e03 Refactor import-tracking to leverage existing AST bindings (#1856)
This PR refactors our import-tracking logic to leverage our existing
logic for tracking bindings. It's both a significant simplification, a
significant improvement (as we can now track reassignments), and closes
out a bunch of subtle bugs.

Though the AST tracks all bindings (e.g., when parsing `import os as
foo`, we bind the name `foo` to a `BindingKind::Importation` that points
to the `os` module), when I went to implement import tracking (e.g., to
ensure that if the user references `List`, it's actually `typing.List`),
I added a parallel system specifically for this use-case.

That was a mistake, for a few reasons:

1. It didn't track reassignments, so if you had `from typing import
List`, but `List` was later overridden, we'd still consider any
reference to `List` to be `typing.List`.
2. It required a bunch of extra logic, include complex logic to try and
optimize the lookups, since it's such a hot codepath.
3. There were a few bugs in the implementation that were just hard to
correct under the existing abstractions (e.g., if you did `from typing
import Optional as Foo`, then we'd treat any reference to `Foo` _or_
`Optional` as `typing.Optional` (even though, in that case, `Optional`
was really unbound).

The new implementation goes through our existing binding tracking: when
we get a reference, we find the appropriate binding given the current
scope stack, and normalize it back to its original target.

Closes #1690.
Closes #1790.
2023-01-13 20:39:54 -05:00
Charlie Marsh
0b92849996 Improve spacing preservation for C405 fixes (#1855)
We now preserve the spacing of the more common form:

```py
set((
    1,
))
```

Rather than the less common form:

```py
set(
    (1,)
)
```
2023-01-13 13:11:08 -05:00
Charlie Marsh
12440ede9c Remove non-magic trailing comma from tuple (#1854)
Closes #1821.
2023-01-13 12:56:42 -05:00
max0x53
fc3f722df5 Implement PLR0133 (ComparisonOfConstants) (#1841)
This PR adds [Pylint
`R0133`](https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/comparison-of-constants.html)

Feel free to suggest changes and additions, I have tried to maintain
parity with the Pylint implementation
[`comparison_checker.py`](https://github.com/PyCQA/pylint/blob/main/pylint/checkers/base/comparison_checker.py#L247)

See #970
2023-01-13 12:14:35 -05:00
Maksudul Haque
84ef7a0171 [isort] Add classes Config Option (#1849)
ref https://github.com/charliermarsh/ruff/issues/1819
2023-01-13 12:13:01 -05:00
Nicola Soranzo
66b1d09362 Clarify that some flake8-bugbear opinionated rules are already implemented (#1847)
E.g. B904 and B905.
2023-01-13 11:49:05 -05:00
Maksudul Haque
3ae01db226 [flake8-bugbear] Fix False Positives for B024 & B027 (#1851)
closes https://github.com/charliermarsh/ruff/issues/1848
2023-01-13 11:46:17 -05:00
Charlie Marsh
048e5774e8 Use absolute paths for --stdin-filename matching (#1843)
Non-basename glob matches (e.g., for `--per-file-ignores`) assume that
the path has been converted to an absolute path. (We do this for
filenames as part of the directory traversal.) For filenames passed via
stdin, though, we're missing this conversion. So `--per-file-ignores`
that rely on the _basename_ worked as expected, but directory paths did
not.

Closes #1840.
2023-01-12 21:01:05 -05:00
max0x53
b47e8e6770 Implement PLR2004 (MagicValueComparison) (#1828)
This PR adds [Pylint
`R2004`](https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/magic-value-comparison.html#magic-value-comparison-r2004)

Feel free to suggest changes and additions, I have tried to maintain
parity with the Pylint implementation
[`magic_value.py`](https://github.com/PyCQA/pylint/blob/main/pylint/extensions/magic_value.py)

See #970
2023-01-12 19:44:18 -05:00
Jan Katins
ef17c82998 Document the way extend-ignore/select are applied (#1839)
Closes: https://github.com/charliermarsh/ruff/issues/1838
2023-01-12 19:44:03 -05:00
Charlie Marsh
9aeb5df5fe Bump version to 0.0.220 2023-01-12 17:57:04 -05:00
Charlie Marsh
7ffba7b552 Use absolute paths for GitHub and Gitlab annotations (#1837)
Note that the _annotation path_ is absolute, while the path encoded in
the message remains relative.

![Screen Shot 2023-01-12 at 5 54 11
PM](https://user-images.githubusercontent.com/1309177/212198531-63f15445-0f6a-471c-a64c-18ad2b6df0c7.png)

Closes #1835.
2023-01-12 17:54:34 -05:00
Charlie Marsh
06473bb1b5 Support for-else loops in SIM110 and SIM111 (#1834)
This PR adds support for `SIM110` and `SIM111` simplifications of the
form:

```py
def f():
    # SIM110
    for x in iterable:
        if check(x):
            return True
    else:
        return False
```
2023-01-12 17:04:58 -05:00
Ash Berlin-Taylor
bf5c048502 Airflow is now using ruff (#1833)
😀
2023-01-12 16:50:01 -05:00
Charlie Marsh
eaed08ae79 Skip SIM110/SIM111 fixes that create long lines 2023-01-12 16:21:54 -05:00
Charlie Marsh
e0fdc4c5e8 Avoid SIM110/SIM110 errors with else statements (#1832)
Closes #1831.
2023-01-12 16:17:27 -05:00
Charlie Marsh
590bec57f4 Fix typo in relative-imports-order option name 2023-01-12 15:57:58 -05:00
Charlie Marsh
3110d342c7 Implement isort's reverse_relative setting (#1826)
This PR implements `reverse-relative`, from isort, but renames it to
`relative-imports-order` with the respected value `closest-to-furthest`
and `furthest-to-closest`, and the latter being the default.

Closes #1813.
2023-01-12 15:48:40 -05:00
nefrob
39aae28eb4 📝 Update readme example for adding isort required imports (#1824)
Fixes use of  isort name to the ruff name.
2023-01-12 13:18:06 -05:00
Charlie Marsh
dcccfe2591 Avoid parsing pyproject.toml files when settings are fixed (#1827)
Apart from being wasteful, this can also cause problems (see the linked
issue).

Resolves #1812.
2023-01-12 13:15:44 -05:00
Martin Fischer
38f5e8f423 Decouple linter module from cache module 2023-01-12 13:09:59 -05:00
Martin Fischer
74f14182ea Decouple resolver module from cli::Overrides 2023-01-12 13:09:59 -05:00
Charlie Marsh
bbc1e7804e Don't trigger SIM401 for complex default values (#1825)
Resolves #1809.
2023-01-12 12:51:23 -05:00
messense
c6320b29e4 Implement autofix for flake8-quotes (#1810)
Resolves #1789
2023-01-12 12:42:28 -05:00
Maksudul Haque
1a90408e8c [flake8-bandit] Add Rule for S701 (jinja2 autoescape false) (#1815)
ref: https://github.com/charliermarsh/ruff/issues/1646

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-12 11:59:20 -05:00
Jeroen Van Goey
07134c50c8 Add usage of ruff in pandas to README (#1811)
pandas now uses ruff for linting, see
https://github.com/pandas-dev/pandas/pull/50160
2023-01-12 10:55:21 -05:00
Charlie Marsh
b36d4a15b0 Modify visibility and shuffle around some modules (#1807) 2023-01-11 23:57:05 -05:00
Charlie Marsh
d8162ce79d Bump version to 0.0.219 2023-01-11 23:46:01 -05:00
Charlie Marsh
e11ef54bda Improve globset documentation and help message (#1808)
Closes #1545.
2023-01-11 23:41:56 -05:00
messense
9a07b0623e Move top level ruff into python folder (#1806)
https://maturin.rs/project_layout.html#mixed-rustpython-project

Resolves #1805
2023-01-11 23:12:55 -05:00
Charlie Marsh
f450e2e79d Implement doc line length enforcement (#1804)
This PR implements `W505` (`DocLineTooLong`), which is similar to `E501`
(`LineTooLong`) but confined to doc lines.

I based the "doc line" definition on pycodestyle, which defines a doc
line as a standalone comment or string statement. Our definition is a
bit more liberal, since we consider any string statement a doc line
(even if it's part of a multi-line statement) -- but that seems fine to
me.

Note that, unusually, this rule requires custom extraction from both the
token stream (to find standalone comments) and the AST (to find string
statements).

Closes #1784.
2023-01-11 22:32:14 -05:00
Colin Delahunty
329946f162 Avoid erroneous Q002 error message for single-quote docstrings (#1777)
Fixes #1775. Before implementing your solution I thought of a slightly
simpler one. However, it will let this function pass:
```
def double_inside_single(a):
    'Double inside "single "'
```
If we want function to pass, my implementation works. But if we do not,
then I can go with how you suggested I implemented this (I left how I
would begin to handle it commented out). The bottom of the flake8-quotes
documentation seems to suggest that this should pass:
https://pypi.org/project/flake8-quotes/

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 20:01:54 -05:00
Charlie Marsh
588399e415 Fix Clippy error 2023-01-11 19:59:00 -05:00
Chammika Mannakkara
4523885268 flake8_simplify : SIM401 (#1778)
Ref #998 

- Implements SIM401 with fix
- Added tests

Notes: 
- only recognize simple ExprKind::Name variables in expr patterns for
now
- bug-fix from reference implementation: check 3-conditions (dict-key,
target-variable, dict-name) to be equal, `flake8_simplify` only test
first two (only first in second pattern)
2023-01-11 19:51:37 -05:00
Maksudul Haque
de81b0cd38 [flake8-simplify] Add Rule for SIM115 (Use context handler for opening files) (#1782)
ref: https://github.com/charliermarsh/ruff/issues/998

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 19:28:05 -05:00
Charlie Marsh
4fce296e3f Skip SIM108 violations for complex if-statements (#1802)
We now skip SIM108 violations if: the resulting statement would exceed
the user-specified line length, or the `if` statement contains comments.

Closes #1719.

Closes #1766.
2023-01-11 19:21:30 -05:00
Charlie Marsh
9d48d7bbd1 Skip unused argument checks for magic methods (#1801)
We still check `__init__`, `__call__`, and `__new__`.

Closes #1796.
2023-01-11 19:02:20 -05:00
Charlie Marsh
c56f263618 Avoid flagging builtins for OSError rewrites (#1800)
Related to (but does not fix) #1790.
2023-01-11 18:49:25 -05:00
Grzegorz Bokota
fb2382fbc3 Update readme to reflect #1763 (#1780)
When checking changes in the 0.0.218 release I noticed that auto fixing
PT004 and PT005 was disabled but this change was not reflected in
README. So I create this small PR to do this.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 18:37:41 -05:00
Charlie Marsh
c92a5a8704 Avoid rewriting flake8-comprehensions expressions for builtin overrides (#1799)
Closes #1788.
2023-01-11 18:33:55 -05:00
Charlie Marsh
d7cf3147b7 Refactor flake8-comprehensions rules to take fewer arguments (#1797) 2023-01-11 18:21:18 -05:00
Charlie Marsh
bf4d35c705 Convert flake8-comprehensions checks to Checker style (#1795) 2023-01-11 18:11:20 -05:00
Charlie Marsh
4e97e9c7cf Improve PIE794 autofix behavior (#1794)
We now: (1) trigger PIE794 for objects without bases (not sure why this
was omitted before); and (2) remove the entire line, rather than leaving
behind trailing whitespace.

Resolves #1787.
2023-01-11 18:01:29 -05:00
Charlie Marsh
a3fcc3b28d Disable update check by default (#1786)
This has received enough criticism that I'm comfortable making it
opt-in.
2023-01-11 13:47:40 -05:00
Charlie Marsh
cfbd068dd5 Bump version to 0.0.218 2023-01-10 21:28:23 -05:00
Charlie Marsh
8aed23fe0a Avoid B023 false-positives for some common builtins (#1776)
This is based on the upstream work in
https://github.com/PyCQA/flake8-bugbear/pull/303 and
https://github.com/PyCQA/flake8-bugbear/pull/305/files.

Resolves #1686.
2023-01-10 21:23:48 -05:00
Colin Delahunty
c016c41c71 Pyupgrade: Format specifiers (#1594)
A part of #827. Posting this for visibility. Still has some work to do
to be done.

Things that still need done before this is ready:

- [x] Does not work when the item is being assigned to a variable
- [x] Does not work if being used in a function call
- [x] Fix incorrectly removed calls in the function
- [x] Has not been tested with pyupgrade negative test cases

Tests from pyupgrade can be seen here:
https://github.com/asottile/pyupgrade/blob/main/tests/features/format_literals_test.py

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-10 20:21:04 -05:00
Charlie Marsh
f1a5e53f06 Enable isort-style required-imports enforcement (#1762)
In isort, this is called `add-imports`, but I prefer the declarative
name.

The idea is that by adding the following to your `pyproject.toml`, you
can ensure that the import is included in all files:

```toml
[tool.ruff.isort]
required-imports = ["from __future__ import annotations"]
```

I mostly reverse-engineered isort's logic for making decisions, though I
made some slight tweaks that I think are preferable. A few comments:

- Like isort, we don't enforce this on empty files (like empty
`__init__.py`).
- Like isort, we require that the import is at the top-level.
- isort will skip any docstrings, and any comments on the first three
lines (I think, based on testing). Ruff places the import after the last
docstring or comment in the file preamble (that is: after the last
docstring or comment that comes before the _first_ non-docstring and
non-comment).

Resolves #1700.
2023-01-10 18:12:57 -05:00
Charlie Marsh
1e94e0221f Disable doctests (#1772)
We don't have any doctests, but `cargo test --all` spends more than half
the time on doctests? A little confusing, but this brings the test time
from > 4s to < 2s on my machine.
2023-01-10 15:10:16 -05:00
Martin Fischer
543865c96b Generate RuleCode::origin() via macro (#1770) 2023-01-10 13:20:43 -05:00
Maksudul Haque
b8e3f0bc13 [flake8-bandit] Add Rule for S508 (snmp insecure version) & S509 (snmp weak cryptography) (#1771)
ref: https://github.com/charliermarsh/ruff/issues/1646

Co-authored-by: messense <messense@icloud.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-10 13:13:54 -05:00
Charlie Marsh
643cedb200 Move CONTRIBUTING.md to top-level (#1768) 2023-01-10 07:38:12 -05:00
Charlie Marsh
91620c378a Disable release builds on CI (#1761) 2023-01-10 07:33:03 -05:00
Harutaka Kawamura
b732135795 Do not autofix PT004 and PT005 (#1763)
As @edgarrmondragon commented in
https://github.com/charliermarsh/ruff/pull/1740#issuecomment-1376230550,
just renaming fixture doesn't work.
2023-01-10 07:24:16 -05:00
messense
9384a081f9 Implement flake8-simplify SIM112 (#1764)
Ref #998
2023-01-10 07:24:01 -05:00
Charlie Marsh
edab268d50 Bump version to 0.0.217 2023-01-09 23:26:22 -05:00
Charlie Marsh
e4fad70a57 Update documentation to match latest terminology (#1760)
Closes #1759.
2023-01-09 21:10:47 -05:00
Charlie Marsh
1a09fff991 Update rule-generation scripts to match latest conventions (#1758)
Resolves #1755.
2023-01-09 19:55:46 -05:00
Charlie Marsh
b85105d2ec Add a helper for any-like operations (#1757) 2023-01-09 19:34:33 -05:00
Charlie Marsh
f7ac28a935 Omit sys.version_info and sys.platform checks from ternary rule (#1756)
Resolves #1753.
2023-01-09 19:22:34 -05:00
Charlie Marsh
9532f342a6 Enable project-specific typing module re-exports (#1754)
Resolves #1744.
2023-01-09 18:17:50 -05:00
Mohamed Daahir
0ee37aa0aa Cache build artifacts using Swatinem/rust-cache@v1 (#1750)
This GitHub Action caches build artifacts in addition to dependencies
which halves the CI duration time.

Resolves #1752.
2023-01-09 15:35:32 -05:00
3247 changed files with 191899 additions and 96418 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",
]

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
* text=auto eol=lf
crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
ruff.schema.json linguist-generated=true text=auto eol=lf

View File

@@ -1,124 +0,0 @@
# Contributing to Ruff
Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.
## The basics
Ruff welcomes contributions in the form of Pull Requests. 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 submitting an [Issue](https://github.com/charliermarsh/ruff/issues) outlining
your proposed change.
If you're looking for a place to start, we recommend implementing a new lint rule (see:
[_Adding a new lint rule_](#example-adding-a-new-lint-rule), which will allow you to learn from and
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
existing Python plugins, which can be used as a reference implementation.
As a concrete example: consider taking on one of the rules in [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998),
and looking to the originating [Python source](https://github.com/MartinThoma/flake8-simplify) for
guidance.
### Prerequisites
Ruff is written in Rust. You'll need to install the
[Rust toolchain](https://www.rust-lang.org/tools/install) for development.
You'll also need [Insta](https://insta.rs/docs/) to update snapshot tests:
```shell
cargo install cargo-insta
```
### Development
After cloning the repository, run Ruff locally with:
```shell
cargo run resources/test/fixtures --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 +nightly fmt --all # Auto-formatting...
cargo +nightly clippy --all # Linting...
cargo +nightly test --all # Testing...
```
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
will save you time and expedite the merge process.
Your Pull Request will be reviewed by a maintainer, which may involve a few rounds of iteration
prior to merging.
### Example: Adding a new lint rule
There are four phases to adding a new lint rule:
1. Define the violation in `src/violations.rs` (e.g., `ModuleImportNotAtTopOfFile`).
2. Map the violation to a code in `src/registry.rs` (e.g., `E402`).
3. Define the _logic_ for triggering the violation in `src/checkers/ast.rs` (for AST-based checks),
`src/checkers/tokens.rs` (for token-based checks), or `src/checkers/lines.rs` (for text-based checks).
4. Add a test fixture.
5. Update the generated files (documentation and generated code).
To define the violation, open up `src/violations.rs`, and define a new struct using the
`define_violation!` macro. There are plenty of examples in that file, so feel free to pattern-match
against the existing structs.
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
collecting diagnostics as it goes.
If you need to inspect the AST, you can run `cargo +nightly 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/[plugin-name]`, named to match
the code you defined earlier (e.g., `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 +nightly 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`.
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/[plugin-name]/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.
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
### Example: Adding a new configuration option
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`.
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.
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
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g.,
`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`.
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
## Release process
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub
Actions, which automatically generates the appropriate wheels across architectures and publishes
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).

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`).
-->

19
.github/release.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes
changelog:
categories:
- title: Breaking Changes
labels:
- breaking
- title: Rules
labels:
- rule
- autofix
- title: Settings
labels:
- configuration
- title: Bug Fixes
labels:
- bug
- title: Other Changes
labels:
- "*"

View File

@@ -4,7 +4,7 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
@@ -13,6 +13,7 @@ concurrency:
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs:
@@ -21,178 +22,113 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
components: rustfmt
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo build --all --release
- run: ./target/release/ruff_dev generate-all
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo +nightly dev generate-all'."
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo +nightly dev generate-all'."
- run: git diff --exit-code -- README.md ruff.schema.json
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- run: cargo build --all
- run: ./target/debug/ruff_dev generate-all
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo dev generate-all'."
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo dev generate-all'."
- run: git diff --exit-code -- README.md ruff.schema.json docs
cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
components: rustfmt
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: "Install Rust toolchain"
run: rustup component add rustfmt
- run: cargo fmt --all --check
cargo_clippy:
cargo-clippy:
name: "cargo clippy"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
components: clippy
target: wasm32-unknown-unknown
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
- run: cargo clippy --workspace --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
- name: "Install Rust toolchain"
run: |
rustup component add clippy
- uses: Swatinem/rust-cache@v1
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo-test:
name: "cargo test"
cargo-clippy-wasm:
name: "cargo clippy (wasm)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: "Install Rust toolchain"
run: |
rustup component add clippy
rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v1
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
cargo-test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: "cargo test | ${{ matrix.os }}"
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- run: cargo install cargo-insta
- run: pip install black[d]==22.12.0
- name: Run tests
- 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
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
- name: "Run tests (Windows)"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
run: |
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.
- run: cargo doc --all --no-deps
env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings"
# TODO(charlie): Re-enable the `wasm-pack` tests.
# See: https://github.com/charliermarsh/ruff/issues/1425
# wasm-pack-test:
# name: "wasm-pack test"
# runs-on: ubuntu-latest
# env:
# WASM_BINDGEN_TEST_TIMEOUT: 60
# steps:
# - uses: actions/checkout@v3
# - uses: actions-rs/toolchain@v1
# with:
# profile: minimal
# toolchain: nightly-2022-11-01
# override: true
# - uses: actions/cache@v3
# env:
# cache-name: cache-cargo
# with:
# path: |
# ~/.cargo/registry
# ~/.cargo/git
# key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
# restore-keys: |
# ${{ runner.os }}-build-${{ env.cache-name }}-
# ${{ runner.os }}-build-
# ${{ runner.os }}-
# - uses: jetli/wasm-pack-action@v0.4.0
# - uses: jetli/wasm-bindgen-action@v0.2.0
# - run: wasm-pack test --node
scripts:
name: "test scripts"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- 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
- run: cargo check
maturin-build:
name: "maturin build"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- run: pip install maturin
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: maturin build -b bin
- run: python scripts/transform_readme.py --target pypi
typos:
name: Spell Check with Typos
name: "spell check"
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v2
- name: Check spelling of file.txt
uses: crate-ci/typos@master
with:
files: .
- uses: actions/checkout@v3
- uses: crate-ci/typos@master
with:
files: .

33
.github/workflows/docs.yaml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: mkdocs
on:
release:
types: [published]
workflow_dispatch:
jobs:
mkdocs:
runs-on: ubuntu-latest
env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- name: "Install dependencies"
run: |
pip install -r docs/requirements.txt
- name: "Copy README File"
run: |
python scripts/transform_readme.py --target mkdocs
python scripts/generate_mkdocs.py
mkdocs build --strict
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@2.0.0
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
command: pages publish site --project-name=ruff-docs --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}

View File

@@ -12,6 +12,7 @@ env:
PYTHON_VERSION: "3.7" # to build abi3 wheels
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs:
@@ -23,22 +24,18 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels - x86_64
uses: messense/maturin-action@v1
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels - x86_64"
uses: PyO3/maturin-action@v1
with:
target: x86_64
args: --release --out dist --sdist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel - x86_64
- name: "Install built wheel - x86_64"
run: |
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -50,21 +47,17 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels - universal2
uses: messense/maturin-action@v1
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels - universal2"
uses: PyO3/maturin-action@v1
with:
args: --release --universal2 --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel - universal2
- name: "Install built wheel - universal2"
run: |
pip install dist/${{ env.CRATE_NAME }}-*universal2.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -80,23 +73,19 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.target }}
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel
- name: "Install built wheel"
shell: bash
run: |
python -m pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -112,18 +101,18 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel
- name: "Install built wheel"
if: matrix.target == 'x86_64'
run: |
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -138,13 +127,13 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- uses: uraimo/run-on-arch-action@v2.0.5
- uses: uraimo/run-on-arch-action@v2.5.0
if: matrix.target != 'ppc64'
name: Install built wheel
with:
@@ -157,8 +146,8 @@ jobs:
pip3 install -U pip
run: |
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -176,13 +165,13 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel
- name: "Install built wheel"
if: matrix.target == 'x86_64-unknown-linux-musl'
uses: addnab/docker-run-action@v3
with:
@@ -191,8 +180,8 @@ jobs:
run: |
apk add py3-pip
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -211,8 +200,8 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
@@ -227,42 +216,8 @@ jobs:
apk add py3-pip
run: |
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
with:
name: wheels
path: dist
pypy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
target: [x86_64, aarch64]
python-version:
- "3.7"
- "3.8"
- "3.9"
exclude:
- os: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: pypy${{ matrix.python-version }}
- name: Build wheels
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel
if: matrix.target == 'x86_64'
run: |
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
@@ -278,13 +233,12 @@ jobs:
- linux-cross
- musllinux
- musllinux-cross
- pypy
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: wheels
- uses: actions/setup-python@v4
- name: Publish to PyPi
- name: "Publish to PyPi"
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.FLAKE8_TO_RUFF_TOKEN }}

View File

@@ -8,21 +8,18 @@ on:
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
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
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
target: wasm32-unknown-unknown
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v3
with:
node-version: 18
@@ -31,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
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

@@ -1,6 +1,7 @@
name: "[ruff] Release"
on:
workflow_dispatch:
release:
types: [published]
@@ -13,6 +14,7 @@ env:
PYTHON_VERSION: "3.7" # to build abi3 wheels
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs:
@@ -24,25 +26,34 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels - x86_64
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - x86_64"
uses: PyO3/maturin-action@v1
with:
target: x86_64
args: --release --out dist --sdist
- name: Install built wheel - x86_64
- name: "Install built wheel - x86_64"
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-x86_64-apple-darwin.tar.gz
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
macos-universal:
runs-on: macos-latest
steps:
@@ -51,105 +62,157 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels - universal2
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - universal2"
uses: PyO3/maturin-action@v1
with:
args: --release --universal2 --out dist
- name: Install built wheel - universal2
- name: "Install built wheel - universal2"
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-aarch64-apple-darwin.tar.gz
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
windows:
runs-on: windows-latest
strategy:
matrix:
target: [x64, x86]
platform:
- target: x86_64-pc-windows-msvc
arch: x64
- target: i686-pc-windows-msvc
arch: x86
- target: aarch64-pc-windows-msvc
arch: x64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.target }}
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
architecture: ${{ matrix.platform.arch }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build wheels
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
target: ${{ matrix.platform.target }}
args: --release --out dist
- name: Install built wheel
- name: "Install built wheel"
if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}
shell: bash
run: |
python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
shell: bash
run: |
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.zip
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.zip
*.sha256
linux:
runs-on: ubuntu-latest
strategy:
matrix:
target: [x86_64, i686]
target:
- x86_64-unknown-linux-gnu
- i686-unknown-linux-gnu
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist
- name: Install built wheel
if: matrix.target == 'x86_64'
- name: "Install built wheel"
if: ${{ startsWith(matrix.target, 'x86_64') }}
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
linux-cross:
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, armv7, s390x, ppc64le, ppc64]
platform:
- target: aarch64-unknown-linux-gnu
arch: aarch64
- target: armv7-unknown-linux-gnueabihf
arch: armv7
- target: s390x-unknown-linux-gnu
arch: s390x
- target: powerpc64le-unknown-linux-gnu
arch: ppc64le
- target: powerpc64-unknown-linux-gnu
arch: ppc64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
target: ${{ matrix.platform.target }}
manylinux: auto
args: --no-default-features --release --out dist
- uses: uraimo/run-on-arch-action@v2.0.5
if: matrix.target != 'ppc64'
args: --release --out dist
- uses: uraimo/run-on-arch-action@v2.5.0
if: matrix.platform.arch != 'ppc64'
name: Install built wheel
with:
arch: ${{ matrix.target }}
arch: ${{ matrix.platform.arch }}
distro: ubuntu20.04
githubToken: ${{ github.token }}
install: |
@@ -158,11 +221,23 @@ jobs:
pip3 install -U pip
run: |
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
musllinux:
runs-on: ubuntu-latest
@@ -177,13 +252,15 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
args: --release --out dist
- name: Install built wheel
- name: "Install built wheel"
if: matrix.target == 'x86_64-unknown-linux-musl'
uses: addnab/docker-run-action@v3
with:
@@ -192,11 +269,23 @@ jobs:
run: |
apk add py3-pip
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
musllinux-cross:
runs-on: ubuntu-latest
@@ -212,8 +301,10 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Build wheels
uses: messense/maturin-action@v1
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
@@ -228,45 +319,23 @@ jobs:
apk add py3-pip
run: |
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
pypy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
target: [x86_64, aarch64]
python-version:
- "3.7"
- "3.8"
- "3.9"
exclude:
- os: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: pypy${{ matrix.python-version }}
- name: Build wheels
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -i pypy${{ matrix.python-version }}
- name: Install built wheel
if: matrix.target == 'x86_64'
- name: "Archive binary"
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: Upload wheels
uses: actions/upload-artifact@v2
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
name: binaries
path: |
*.tar.gz
*.sha256
release:
name: Release
@@ -279,17 +348,27 @@ jobs:
- linux-cross
- musllinux
- musllinux-cross
- pypy
if: "startsWith(github.ref, 'refs/tags/')"
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: wheels
- uses: actions/setup-python@v4
- name: Publish to PyPi
- name: "Publish to PyPi"
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.RUFF_TOKEN }}
run: |
pip install --upgrade twine
twine upload --skip-existing *
- name: "Update pre-commit mirror"
run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.RUFF_PRE_COMMIT_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/charliermarsh/ruff-pre-commit/dispatches --data '{"event_type": "pypi_release"}'
- uses: actions/download-artifact@v3
with:
name: binaries
path: binaries
- name: Release
uses: softprops/action-gh-release@v1
with:
files: binaries/*

11
.gitignore vendored
View File

@@ -1,6 +1,8 @@
# Local cache
.ruff_cache
resources/test/cpython
crates/ruff/resources/test/cpython
mkdocs.yml
.overrides
###
# Rust.gitignore
@@ -182,3 +184,10 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
.vimspector.json
# Visual Studio Code
.vscode/
# VIM
.*.sw?
.sw?

View File

@@ -1,10 +1,68 @@
fail_fast: true
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.216
hooks:
- id: ruff
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.10.1
hooks:
- id: validate-pyproject
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.16
hooks:
- id: mdformat
additional_dependencies:
- mdformat-black
- black==23.1.0 # Must be the latest version of Black
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.33.0
hooks:
- id: markdownlint-fix
args:
- --disable
- MD013 # line-length
- MD033 # no-inline-html
- --
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: rust
types: [rust]
- id: clippy
name: clippy
entry: cargo clippy --workspace --all-targets --all-features -- -D warnings
language: rust
pass_filenames: false
- id: ruff
name: ruff
entry: cargo run -p ruff_cli -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
language: rust
types_or: [python, pyi]
require_serial: true
exclude: |
(?x)^(
crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.*
)$
- id: dev-generate-all
name: dev-generate-all
entry: cargo dev generate-all
language: rust
pass_filenames: false
exclude: target
# Black
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
exclude: |
(?x)^(
crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.*
)$
ci:
skip: [cargo-fmt, clippy, dev-generate-all]

View File

@@ -1,5 +1,130 @@
# Breaking Changes
## 0.0.246
### `multiple-statements-on-one-line-def` (`E704`) was removed ([#2773](https://github.com/charliermarsh/ruff/pull/2773))
This rule was introduced in v0.0.245. However, it turns out that pycodestyle and Flake8 ignore this
rule by default, as it is not part of PEP 8. As such, we've removed it from Ruff.
## 0.0.245
### Ruff's public `check` method was removed ([#2709](https://github.com/charliermarsh/ruff/pull/2709))
Previously, Ruff exposed a `check` method as a public Rust API. This method was used by few,
if any clients, and was not well documented or supported. As such, it has been removed, with
the intention of adding a stable public API in the future.
## 0.0.238
### `select`, `extend-select`, `ignore`, and `extend-ignore` have new semantics ([#2312](https://github.com/charliermarsh/ruff/pull/2312))
Previously, the interplay between `select` and its related options could lead to unexpected
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
examples.)
When Ruff determines the enabled rule set, it has to reconcile `select` and `ignore` from a variety
of sources, including the current `pyproject.toml`, any inherited `pyproject.toml` files, and the
CLI.
The new semantics are such that Ruff uses the "highest-priority" `select` as the basis for the rule
set, and then applies any `extend-select`, `ignore`, and `extend-ignore` adjustments. CLI options
are given higher priority than `pyproject.toml` options, and the current `pyproject.toml` file is
given higher priority than any inherited `pyproject.toml` files.
`extend-select` and `extend-ignore` are no longer given "top priority"; instead, they merely append
to the `select` and `ignore` lists, as in Flake8.
This change is largely backwards compatible -- most users should experience no change in behavior.
However, as an example of a breaking change, consider the following:
```toml
[tool.ruff]
ignore = ["F401"]
```
Running `ruff --select F` would previously have enabled all `F` rules, apart from `F401`. Now, it
will enable all `F` rules, including `F401`, as the command line's `--select` resets the resolution.
### `remove-six-compat` (`UP016`) has been removed ([#2332](https://github.com/charliermarsh/ruff/pull/2332))
The `remove-six-compat` rule has been removed. This rule was only useful for one-time Python 2-to-3
upgrades.
## 0.0.237
### `--explain`, `--clean`, and `--generate-shell-completion` are now subcommands ([#2190](https://github.com/charliermarsh/ruff/pull/2190))
`--explain`, `--clean`, and `--generate-shell-completion` are now implemented as subcommands:
```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.)
# 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:
- Subcommands will now fail when invoked with unsupported arguments, instead
of silently ignoring them. For example, the following will now fail:
```console
ruff --clean --respect-gitignore
```
(the `clean` command doesn't support `--respect-gitignore`.)
- The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
For example, prior to this release, running `ruff rule` would run `ruff` over a file or
directory called `rule`. Now, `ruff rule` would invoke the `rule` subcommand. This should
only impact projects with files or directories named `rule`, `check`, `explain`, `clean`,
or `generate-shell-completion`.
- Scripts that invoke ruff should supply `--` before any positional arguments.
(The semantics of `ruff -- <arg>` have not changed.)
- `--explain` previously treated `--format grouped` as a synonym for `--format text`.
This is no longer supported; instead, use `--format text`.
## 0.0.226
### `misplaced-comparison-constant` (`PLC2201`) was deprecated in favor of `SIM300` ([#1980](https://github.com/charliermarsh/ruff/pull/1980))
These two rules contain (nearly) identical logic. To deduplicate the rule set, we've upgraded
`SIM300` to handle a few more cases, and deprecated `PLC2201` in favor of `SIM300`.
## 0.0.225
### `@functools.cache` rewrites have been moved to a standalone rule (`UP033`) ([#1938](https://github.com/charliermarsh/ruff/pull/1938))
Previously, `UP011` handled both `@functools.lru_cache()`-to-`@functools.lru_cache` conversions,
_and_ `@functools.lru_cache(maxsize=None)`-to-`@functools.cache` conversions. The latter has been
moved out to its own rule (`UP033`). As such, some `# noqa: UP011` comments may need to be updated
to reflect the change in rule code.
## 0.0.222
### `--max-complexity` has been removed from the CLI ([#1877](https://github.com/charliermarsh/ruff/pull/1877))
The McCabe plugin's `--max-complexity` setting has been removed from the CLI, for consistency with
the treatment of other, similar settings.
To set the maximum complexity, use the `max-complexity` property in your `pyproject.toml` file,
like so:
```toml
[tool.ruff.mccabe]
max-complexity = 10
```
## 0.0.181
### Files excluded by `.gitignore` are now ignored ([#1234](https://github.com/charliermarsh/ruff/pull/1234))

View File

@@ -1,5 +1,17 @@
# Contributor Covenant Code of Conduct
- [Our Pledge](#our-pledge)
- [Our Standards](#our-standards)
- [Enforcement Responsibilities](#enforcement-responsibilities)
- [Scope](#scope)
- [Enforcement](#enforcement)
- [Enforcement Guidelines](#enforcement-guidelines)
- [1. Correction](#1-correction)
- [2. Warning](#2-warning)
- [3. Temporary Ban](#3-temporary-ban)
- [4. Permanent Ban](#4-permanent-ban)
- [Attribution](#attribution)
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
@@ -17,23 +29,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
@@ -106,7 +118,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 +127,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](https://www.contributor-covenant.org/faq).
Translations are available [here](https://www.contributor-covenant.org/translations).
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.
[homepage]: https://www.contributor-covenant.org

339
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,339 @@
# Contributing to Ruff
Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.
- [The Basics](#the-basics)
- [Prerequisites](#prerequisites)
- [Development](#development)
- [Project Structure](#project-structure)
- [Example: Adding a new lint rule](#example-adding-a-new-lint-rule)
- [Rule naming convention](#rule-naming-convention)
- [Example: Adding a new configuration option](#example-adding-a-new-configuration-option)
- [MkDocs](#mkdocs)
- [Release Process](#release-process)
- [Benchmarks](#benchmarks)
## The Basics
Ruff welcomes contributions in the form of Pull Requests.
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/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:
[_Adding a new lint rule_](#example-adding-a-new-lint-rule), which will allow you to learn from and
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
existing Python plugins, which can be used as a reference implementation.
As a concrete example: consider taking on one of the rules from the [`flake8-pyi`](https://github.com/charliermarsh/ruff/issues/848)
plugin, and looking to the originating [Python source](https://github.com/PyCQA/flake8-pyi)
for guidance.
### Prerequisites
Ruff is written in Rust. You'll need to install the
[Rust toolchain](https://www.rust-lang.org/tools/install) for development.
You'll also need [Insta](https://insta.rs/docs/) to update snapshot tests:
```shell
cargo install cargo-insta
```
### Development
After cloning the repository, run Ruff locally with:
```shell
cargo run -p ruff_cli -- check /path/to/file.py --no-cache
```
Prior to opening a pull request, ensure that your code has been auto-formatted,
and that it passes both the lint and test validation checks:
```shell
cargo fmt # Auto-formatting...
cargo clippy --fix --workspace --all-targets --all-features # Linting...
cargo test # Testing...
```
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
will save you time and expedite the merge process.
Note that many code changes also require updating the snapshot tests, which is done interactively
after running `cargo test` like so:
```shell
cargo insta review
```
If you have `pre-commit` [installed](https://pre-commit.com/#installation) then you can use it to
assist with formatting and linting. The following command will run the `pre-commit` hooks:
```shell
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. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention).
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
1. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
1. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
(for text-based checks), or `crates/ruff/src/checkers/filesystem.rs` (for filesystem-based
checks).
1. Add a test fixture.
1. Update the generated files (documentation and generated code).
To define the violation, start by creating a dedicated file for your rule under the appropriate
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
contain a struct defined via `define_violation!`, along with a function that creates the violation
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 `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 `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 -p ruff_cli -- check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
`test_case` macro in the relevant `crates/ruff/src/[linter]/mod.rs` file. Then, run `cargo test`.
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.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
#### Rule naming convention
The rule name should make sense when read as "allow _rule-name_" or "allow _rule-name_ items".
This implies that rule names:
- should state the bad thing being checked for
- should not contain instructions on what you what you should use instead
(these belong in the rule documentation and the `autofix_title` for rules that have autofix)
When re-implementing rules from other linters, this convention is given more importance than
preserving the original rule name.
### Example: Adding a new configuration option
Ruff's user-facing settings live in a few different places.
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 `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
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g.,
`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 `crates/ruff/src/flake8_to_ruff/converter.rs`.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
## MkDocs
To preview any changes to the documentation locally:
1. Install MkDocs and Material for MkDocs with:
```shell
pip install -r docs/requirements.txt
```
1. Generate the MkDocs site with:
```shell
python scripts/generate_mkdocs.py
```
1. Run the development server with:
```shell
mkdocs serve
```
The documentation should then be available locally at
[http://127.0.0.1:8000/docs/](http://127.0.0.1:8000/docs/).
## Release Process
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub
Actions, which automatically generates the appropriate wheels across architectures and publishes
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
```

1171
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +1,27 @@
[workspace]
members = [
"flake8_to_ruff",
"ruff_dev",
]
members = ["crates/*"]
[package]
name = "ruff"
version = "0.0.216"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
[workspace.package]
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"
rust-version = "1.67.0"
[lib]
name = "ruff"
crate-type = ["cdylib", "rlib"]
[dependencies]
annotate-snippets = { version = "0.9.1", features = ["color"] }
[workspace.dependencies]
anyhow = { version = "1.0.66" }
atty = { version = "0.2.14" }
bincode = { version = "1.3.3" }
bitflags = { version = "1.3.2" }
cachedir = { version = "0.3.0" }
cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { version = "4.0.1", features = ["derive", "env"] }
clap_complete_command = { version = "0.4.0" }
colored = { version = "2.0.0" }
dirs = { version = "4.0.0" }
fern = { version = "0.6.1" }
filetime = { version = "0.2.17" }
glob = { version = "0.3.0" }
globset = { version = "0.4.9" }
ignore = { version = "0.4.18" }
clap = { version = "4.0.1", features = ["derive"] }
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" }
notify = { version = "5.0.0" }
num-bigint = { version = "0.4.3" }
num-traits = "0.2.15"
is-macro = { version = "0.2.2" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
quick-junit = { version = "0.3.2" }
regex = { version = "1.6.0" }
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
ruff_macros = { version = "0.0.216", path = "ruff_macros" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "d532160333ffeb6dbeca2c2728c2391cd1e53b7f" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "d532160333ffeb6dbeca2c2728c2391cd1e53b7f" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "d532160333ffeb6dbeca2c2728c2391cd1e53b7f" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "aa8336ee94492b52458ed8e1517238e5c6c2914c" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "aa8336ee94492b52458ed8e1517238e5c6c2914c" }
schemars = { version = "0.8.11" }
semver = { version = "1.0.16" }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = { version = "1.0.87" }
shellexpand = { version = "3.0.0" }
similar = { version = "2.2.1" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
textwrap = { version = "0.16.0" }
titlecase = { version = "2.2.1" }
toml_edit = { version = "0.17.1", features = ["easy"] }
walkdir = { version = "2.3.2" }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
clearscreen = { version = "2.0.0" }
rayon = { version = "1.5.3" }
update-informer = { version = "0.6.0", default-features = false, features = ["pypi"], optional = true }
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
# For (future) wasm-pack support
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2.7", features = ["js"] }
console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "0.2.0" }
serde-wasm-bindgen = { version = "0.4" }
js-sys = { version = "0.3.60" }
wasm-bindgen = { version = "0.2.83" }
[dev-dependencies]
insta = { version = "1.19.1", features = ["yaml"] }
test-case = { version = "2.2.2" }
ureq = { version = "2.5.0", features = [] }
wasm-bindgen-test = { version = "0.3.33" }
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
assert_cmd = { version = "2.0.4" }
criterion = { version = "0.4.0" }
[features]
default = ["update-informer"]
update-informer = ["dep:update-informer"]
toml = { version = "0.6.0" }
[profile.release]
panic = "abort"
@@ -114,7 +39,3 @@ opt-level = 3
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
[profile.dev.package.rustpython-parser]
opt-level = 1
[[bench]]
name = "source_code_locator"
harness = false

1095
LICENSE

File diff suppressed because it is too large Load Diff

3170
README.md

File diff suppressed because it is too large Load Diff

7
_typos.toml Normal file
View File

@@ -0,0 +1,7 @@
[files]
extend-exclude = ["snapshots", "black"]
[default.extend-words]
trivias = "trivias"
hel = "hel"
whos = "whos"

View File

@@ -1,18 +0,0 @@
use std::fs;
use std::path::Path;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use ropey::Rope;
fn criterion_benchmark(c: &mut Criterion) {
let contents = fs::read_to_string(Path::new("resources/test/fixtures/D.py")).unwrap();
c.bench_function("rope", |b| {
b.iter(|| {
let rope = Rope::from_str(black_box(&contents));
rope.line_to_char(black_box(4));
});
});
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

7
clippy.toml Normal file
View File

@@ -0,0 +1,7 @@
doc-valid-idents = [
"StackOverflow",
"CodeQL",
"IPython",
"NumPy",
"..",
]

View File

@@ -0,0 +1,20 @@
[package]
name = "flake8-to-ruff"
version = "0.0.253"
edition = { workspace = true }
rust-version = { workspace = true }
[dependencies]
anyhow = { workspace = true }
clap = { workspace = true }
colored = { version = "2.0.0" }
configparser = { version = "3.0.2" }
once_cell = { workspace = true }
regex = { workspace = true }
ruff = { path = "../ruff", default-features = false }
rustc-hash = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
strum = { workspace = true }
strum_macros = { workspace = true }
toml = { workspace = true }

View File

@@ -0,0 +1,98 @@
# flake8-to-ruff
Convert existing Flake8 configuration files (`setup.cfg`, `tox.ini`, or `.flake8`) for use with
[Ruff](https://github.com/charliermarsh/ruff).
Generates a Ruff-compatible `pyproject.toml` section.
## Installation and Usage
### Installation
Available as [`flake8-to-ruff`](https://pypi.org/project/flake8-to-ruff/) on PyPI:
```shell
pip install flake8-to-ruff
```
### Usage
To run `flake8-to-ruff`:
```shell
flake8-to-ruff path/to/setup.cfg
flake8-to-ruff path/to/tox.ini
flake8-to-ruff path/to/.flake8
```
`flake8-to-ruff` will print the relevant `pyproject.toml` sections to standard output, like so:
```toml
[tool.ruff]
exclude = [
'.svn',
'CVS',
'.bzr',
'.hg',
'.git',
'__pycache__',
'.tox',
'.idea',
'.mypy_cache',
'.venv',
'node_modules',
'_state_machine.py',
'test_fstring.py',
'bad_coding2.py',
'badsyntax_*.py',
]
select = [
'A',
'E',
'F',
'Q',
]
ignore = []
[tool.ruff.flake8-quotes]
inline-quotes = 'single'
[tool.ruff.pep8-naming]
ignore-names = [
'foo',
'bar',
]
```
### Plugins
`flake8-to-ruff` will attempt to infer any activated plugins based on the settings provided in your
configuration file.
For example, if your `.flake8` file includes a `docstring-convention` property, `flake8-to-ruff`
will enable the appropriate [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
checks.
Alternatively, you can manually specify plugins on the command-line:
```shell
flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
```
## Limitations
1. Ruff only supports a subset of the Flake configuration options. `flake8-to-ruff` will warn on and
ignore unsupported options in the `.flake8` file (or equivalent). (Similarly, Ruff has a few
configuration options that don't exist in Flake8.)
1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
codes from unsupported plugins. (See the [Ruff README](https://github.com/charliermarsh/ruff#user-content-how-does-ruff-compare-to-flake8)
for the complete list of supported plugins.)
## License
MIT
## Contributing
Contributions are welcome and hugely appreciated. To get started, check out the
[contributing guidelines](https://github.com/charliermarsh/ruff/blob/main/CONTRIBUTING.md).

View File

@@ -0,0 +1,61 @@
//! Utility to generate Ruff's `pyproject.toml` section from a Flake8 INI file.
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(
about = "Convert existing Flake8 configuration to Ruff.",
long_about = None
)]
struct Args {
/// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or
/// `.flake8`).
#[arg(required = true)]
file: PathBuf,
/// Optional path to a `pyproject.toml` file, used to ensure compatibility
/// with Black.
#[arg(long)]
pyproject: Option<PathBuf>,
/// List of plugins to enable.
#[arg(long, value_delimiter = ',')]
plugin: Option<Vec<flake8_to_ruff::Plugin>>,
}
fn main() -> Result<()> {
set_up_logging(&LogLevel::Default)?;
let args = Args::parse();
// Read the INI file.
let mut ini = Ini::new_cs();
ini.set_multiline(true);
let config = ini.load(args.file).map_err(|msg| anyhow::anyhow!(msg))?;
// Read the pyproject.toml file.
let pyproject = args.pyproject.map(flake8_to_ruff::parse).transpose()?;
let external_config = pyproject
.as_ref()
.and_then(|pyproject| pyproject.tool.as_ref())
.map(|tool| ExternalConfig {
black: tool.black.as_ref(),
isort: tool.isort.as_ref(),
})
.unwrap_or_default();
// Create Ruff's pyproject.toml section.
let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?;
#[allow(clippy::print_stdout)]
{
println!("{}", toml::to_string_pretty(&pyproject)?);
}
Ok(())
}

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

@@ -0,0 +1,83 @@
[package]
name = "ruff"
version = "0.0.253"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
edition = { workspace = true }
rust-version = { workspace = true }
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]
ruff_macros = { path = "../ruff_macros" }
ruff_python = { path = "../ruff_python" }
ruff_rustpython = { path = "../ruff_rustpython" }
anyhow = { workspace = true }
bisection = { version = "0.1.0" }
bitflags = { version = "1.3.2" }
cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { workspace = true, features = ["derive", "env", "string"] }
colored = { version = "2.0.0" }
derivative = { version = "2.2.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" }
is-macro = { workspace = true }
itertools = { workspace = true }
libcst = { workspace = true }
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 = { workspace = true }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
regex = { workspace = true }
result-like = "0.4.6"
rustc-hash = { workspace = true }
rustpython-common = { workspace = true }
rustpython-parser = { workspace = true }
schemars = { workspace = true }
semver = { version = "1.0.16" }
serde = { workspace = true }
shellexpand = { version = "3.0.0" }
smallvec = { version = "1.10.0" }
strum = { workspace = true }
strum_macros = { workspace = true }
textwrap = { version = "0.16.0" }
thiserror = { version = "1.0" }
titlecase = { version = "2.2.1" }
toml = { workspace = true }
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-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" }
[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,4 @@
avoid-*
do-not-*
uses-*
*-used

View File

@@ -0,0 +1,9 @@
class C:
from typing import overload
@overload
def f(self, x: int, y: int) -> None:
...
def f(self, x, y):
pass

View File

@@ -103,3 +103,11 @@ class Foo:
@classmethod
def foo(cls, a: int, b: int) -> int:
pass
# ANN101
def foo(self, /, a: int, b: int) -> int:
pass
# OK
def f(*args: *tuple[int]) -> None: ...

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

@@ -0,0 +1,48 @@
"""Test case expected to be run with `mypy_init_return = True`."""
# Error
class Foo:
def __init__(self):
...
# Error
class Foo:
def __init__(self, foo):
...
# OK
class Foo:
def __init__(self, foo) -> None:
...
# OK
class Foo:
def __init__(self) -> None:
...
# OK
class Foo:
def __init__(self, foo: int):
...
# OK
class Foo:
def __init__(self, foo: int) -> None:
...
# Error
def __init__(self, foo: int):
...
# Error used to be ok for a moment since the mere presence
# of a vararg falsely indicated that the function has a typed argument.
class Foo:
def __init__(self, *arg):
...

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

@@ -4,6 +4,7 @@ d = {}
safe = "s3cr3t"
password = True
password = safe
password = ""
password is True
password == 1
d["safe"] = "s3cr3t"
@@ -18,6 +19,8 @@ token = "s3cr3t"
secrete = "s3cr3t"
safe = password = "s3cr3t"
password = safe = "s3cr3t"
PASSWORD = "s3cr3t"
PassWord = "s3cr3t"
d["password"] = "s3cr3t"
d["pass"] = "s3cr3t"
@@ -60,3 +63,15 @@ if token == "3\t4":
if token == "5\r6":
pass
# These should not be flagged
passed_msg = "You have passed!"
compassion = "Please don't match!"
impassable = "You shall not pass!"
passwords = ""
PASSWORDS = ""
passphrases = ""
PassPhrases = ""
tokens = ""
secrets = ""

View File

@@ -7,6 +7,7 @@ string = "Hello World"
# OK
func("s3cr3t")
func(1, password=string)
func(1, password="")
func(pos="s3cr3t", password=string)
# Error

View File

@@ -28,3 +28,7 @@ def ok_all(first, /, pos, default="posonly", *, kwonly="kwonly"):
def default_all(first, /, pos, secret="posonly", *, password="kwonly"):
pass
def ok_empty(first, password=""):
pass

View File

@@ -0,0 +1,14 @@
try:
pass
except Exception:
pass
try:
pass
except:
pass
try:
pass
except ValueError:
pass

View File

@@ -0,0 +1,29 @@
try:
pass
except Exception:
continue
try:
pass
except:
continue
try:
pass
except (Exception,):
continue
try:
pass
except (Exception, ValueError):
continue
try:
pass
except ValueError:
continue
try:
pass
except (ValueError,):
continue

View File

@@ -0,0 +1,6 @@
from pysnmp.hlapi import CommunityData
CommunityData("public", mpModel=0) # S508
CommunityData("public", mpModel=1) # S508
CommunityData("public", mpModel=2) # OK

View File

@@ -0,0 +1,7 @@
from pysnmp.hlapi import UsmUserData
insecure = UsmUserData("securityName") # S509
auth_no_priv = UsmUserData("securityName", "authName") # S509
less_insecure = UsmUserData("securityName", "authName", "privName") # OK

View File

@@ -0,0 +1,95 @@
# single-line failures
query1 = "SELECT %s FROM table" % (var,) # bad
query2 = "SELECT var FROM " + table
query3 = "SELECT " + val + " FROM " + table
query4 = "SELECT {} FROM table;".format(var)
query5 = f"SELECT * FROM table WHERE var = {var}"
query6 = "DELETE FROM table WHERE var = %s" % (var,)
query7 = "DELETE FROM table WHERE VAR = " + var
query8 = "DELETE FROM " + table + "WHERE var = " + var
query9 = "DELETE FROM table WHERE var = {}".format(var)
query10 = f"DELETE FROM table WHERE var = {var}"
query11 = "INSERT INTO table VALUES (%s)" % (var,)
query12 = "INSERT INTO TABLE VALUES (" + var + ")"
query13 = "INSERT INTO {} VALUES ({})".format(table, var)
query14 = f"INSERT INTO {table} VALUES var = {var}"
query15 = "UPDATE %s SET var = %s" % (table, var)
query16 = "UPDATE " + table + " SET var = " + var
query17 = "UPDATE {} SET var = {}".format(table, var)
query18 = f"UPDATE {table} SET var = {var}"
query19 = "select %s from table" % (var,)
query20 = "select var from " + table
query21 = "select " + val + " from " + table
query22 = "select {} from table;".format(var)
query23 = f"select * from table where var = {var}"
query24 = "delete from table where var = %s" % (var,)
query25 = "delete from table where var = " + var
query26 = "delete from " + table + "where var = " + var
query27 = "delete from table where var = {}".format(var)
query28 = f"delete from table where var = {var}"
query29 = "insert into table values (%s)" % (var,)
query30 = "insert into table values (" + var + ")"
query31 = "insert into {} values ({})".format(table, var)
query32 = f"insert into {table} values var = {var}"
query33 = "update %s set var = %s" % (table, var)
query34 = "update " + table + " set var = " + var
query35 = "update {} set var = {}".format(table, var)
query36 = f"update {table} set var = {var}"
# multi-line failures
def query37():
return """
SELECT *
FROM table
WHERE var = %s
""" % var
def query38():
return """
SELECT *
FROM TABLE
WHERE var =
""" + var
def query39():
return """
SELECT *
FROM table
WHERE var = {}
""".format(var)
def query40():
return f"""
SELECT *
FROM table
WHERE var = {var}
"""
def query41():
return (
"SELECT *"
"FROM table"
f"WHERE var = {var}"
)
# # cursor-wrapped failures
query42 = cursor.execute("SELECT * FROM table WHERE var = %s" % var)
query43 = cursor.execute(f"SELECT * FROM table WHERE var = {var}")
query44 = cursor.execute("SELECT * FROM table WHERE var = {}".format(var))
query45 = cursor.executemany("SELECT * FROM table WHERE var = %s" % var, [])
# # pass
query = "SELECT * FROM table WHERE id = 1"
query = "DELETE FROM table WHERE id = 1"
query = "INSERT INTO table VALUES (1)"
query = "UPDATE table SET id = 1"
cursor.execute('SELECT * FROM table WHERE id = %s', var)
cursor.execute('SELECT * FROM table WHERE id = 1')
cursor.executemany('SELECT * FROM table WHERE id = %s', [var, var2])

View File

@@ -0,0 +1,8 @@
import logging.config
t = logging.config.listen(9999)
def verify_func():
pass
l = logging.config.listen(9999, verify=verify_func)

View File

@@ -0,0 +1,29 @@
import jinja2
from jinja2 import Environment, select_autoescape
templateLoader = jinja2.FileSystemLoader( searchpath="/" )
something = ''
Environment(loader=templateLoader, load=templateLoader, autoescape=True)
templateEnv = jinja2.Environment(autoescape=True,
loader=templateLoader )
Environment(loader=templateLoader, load=templateLoader, autoescape=something) # S701
templateEnv = jinja2.Environment(autoescape=False, loader=templateLoader ) # S701
Environment(loader=templateLoader,
load=templateLoader,
autoescape=False) # S701
Environment(loader=templateLoader, # S701
load=templateLoader)
Environment(loader=templateLoader, autoescape=select_autoescape())
Environment(loader=templateLoader,
autoescape=select_autoescape(['html', 'htm', 'xml']))
Environment(loader=templateLoader,
autoescape=jinja2.select_autoescape(['html', 'htm', 'xml']))
def fake_func():
return 'foobar'
Environment(loader=templateLoader, autoescape=fake_func()) # S701

View File

@@ -0,0 +1,94 @@
try:
pass
except ValueError:
pass
except Exception as e:
raise e
finally:
pass
try:
pass
except BaseException as e:
raise e
except TypeError:
pass
else:
pass
try:
pass
except Exception as e:
raise e
except BaseException:
pass
try:
pass
except Exception:
pass
finally:
try:
pass
except BaseException as e:
raise e
try:
pass
except Exception as e:
try:
raise e
except BaseException:
pass
try:
try:
pass
except BaseException as e:
raise e
except Exception:
pass
try:
pass
except Exception as e:
raise bad
except BaseException:
pass
import logging
try:
pass
except Exception:
logging.error("...")
try:
pass
except Exception:
logging.error("...", exc_info=False)
try:
pass
except Exception:
logging.error("...", exc_info=None)
try:
pass
except Exception:
logging.exception("...")
try:
pass
except Exception:
logging.error("...", exc_info=True)

View File

@@ -0,0 +1,82 @@
def function(
posonly_nohint,
posonly_nonboolhint: int,
posonly_boolhint: bool,
posonly_boolstrhint: "bool",
/,
offset,
posorkw_nonvalued_nohint,
posorkw_nonvalued_nonboolhint: int,
posorkw_nonvalued_boolhint: bool,
posorkw_nonvalued_boolstrhint: "bool",
posorkw_boolvalued_nohint=True,
posorkw_boolvalued_nonboolhint: int = True,
posorkw_boolvalued_boolhint: bool = True,
posorkw_boolvalued_boolstrhint: "bool" = True,
posorkw_nonboolvalued_nohint=1,
posorkw_nonboolvalued_nonboolhint: int = 2,
posorkw_nonboolvalued_boolhint: bool = 3,
posorkw_nonboolvalued_boolstrhint: "bool" = 4,
*,
kwonly_nonvalued_nohint,
kwonly_nonvalued_nonboolhint: int,
kwonly_nonvalued_boolhint: bool,
kwonly_nonvalued_boolstrhint: "bool",
kwonly_boolvalued_nohint=True,
kwonly_boolvalued_nonboolhint: int = False,
kwonly_boolvalued_boolhint: bool = True,
kwonly_boolvalued_boolstrhint: "bool" = True,
kwonly_nonboolvalued_nohint=5,
kwonly_nonboolvalued_nonboolhint: int = 1,
kwonly_nonboolvalued_boolhint: bool = 1,
kwonly_nonboolvalued_boolstrhint: "bool" = 1,
**kw,
):
...
def used(do):
return do
used("a", True)
used(do=True)
# Avoid FBT003 for explicitly allowed methods.
"""
FBT003 Boolean positional value on dict
"""
a = {"a": "b"}
a.get("hello", False)
{}.get("hello", False)
{}.setdefault("hello", True)
{}.pop("hello", False)
{}.pop(True, False)
dict.fromkeys(("world",), True)
{}.deploy(True, False)
getattr(someobj, attrname, False)
mylist.index(True)
int(True)
str(int(False))
cfg.get("hello", True)
cfg.getint("hello", True)
cfg.getfloat("hello", True)
cfg.getboolean("hello", True)
class Registry:
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
@foo.setter
def foo(self, value: bool) -> None:
pass
# FBT001: Boolean positional arg in function definition
def foo(self, value: bool) -> None:
pass

View File

@@ -17,6 +17,11 @@ s.rstrip(".facebook.com") # warning
s.rstrip("e") # no warning
s.rstrip("\n\t ") # no warning
s.rstrip(r"\n\t ") # warning
s.strip("a") # no warning
s.strip("") # no warning
s.strip("ああ") # warning
s.strip("\ufeff") # no warning
s.strip("\u0074\u0065\u0073\u0074") # warning
from somewhere import other_type, strip

View File

@@ -0,0 +1,88 @@
for i in range(10):
print(i)
print(i) # name no longer defined on Python 3; no warning yet
for i in range(10): # name not used within the loop; B007
print(10)
print(i) # name no longer defined on Python 3; no warning yet
for _ in range(10): # _ is okay for a throw-away variable
print(10)
for i in range(10):
for j in range(10):
for k in range(10): # k not used, i and j used transitively
print(i + j)
def strange_generator():
for i in range(10):
for j in range(10):
for k in range(10):
for l in range(10):
yield i, (j, (k, l))
for i, (j, (k, l)) in strange_generator(): # i, k not used
print(j, l)
FMT = "{foo} {bar}"
for foo, bar in [(1, 2)]:
if foo:
print(FMT.format(**locals()))
for foo, bar in [(1, 2)]:
if foo:
print(FMT.format(**globals()))
for foo, bar in [(1, 2)]:
if foo:
print(FMT.format(**vars()))
for foo, bar in [(1, 2)]:
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()

View File

@@ -1,7 +1,7 @@
"""
Should emit:
B009 - Line 18, 19, 20, 21, 22
B010 - Line 33, 34, 35, 36
B009 - Line 19, 20, 21, 22, 23, 24
B010 - Line 40, 41, 42, 43, 44, 45
"""
# Valid getattr usage
@@ -13,10 +13,12 @@ getattr(foo, bar, None)
getattr(foo, "123abc")
getattr(foo, r"123\abc")
getattr(foo, "except")
getattr(foo, "__123abc")
# Invalid usage
getattr(foo, "bar")
getattr(foo, "_123abc")
getattr(foo, "__123abc__")
getattr(foo, "abc123")
getattr(foo, r"abc123")
_ = lambda x: getattr(x, "bar")
@@ -27,6 +29,7 @@ if getattr(x, "bar"):
setattr(foo, bar, None)
setattr(foo, "bar{foo}".format(foo="a"), None)
setattr(foo, "123abc", None)
setattr(foo, "__123abc", None)
setattr(foo, r"123\abc", None)
setattr(foo, "except", None)
_ = lambda x: setattr(x, "bar", 1)
@@ -36,6 +39,7 @@ if setattr(x, "bar", 1):
# Invalid usage
setattr(foo, "bar", None)
setattr(foo, "_123abc", None)
setattr(foo, "__123abc__", None)
setattr(foo, "abc123", None)
setattr(foo, r"abc123", None)
setattr(foo.bar, r"baz", None)

View File

@@ -105,3 +105,25 @@ while True:
pass
finally:
break # warning
while True:
try:
pass
finally:
match *0, 1, *2:
case 0,:
y = 0
case 0, *x:
break # warning
while True:
try:
pass
finally:
match *0, 1, *2:
case 0,:
y = 0
case 0, *x:
pass # no warning

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