[pycodestyle] Add blank line(s) rules (E301, E302, E303, E304, E305, E306)#8720
[pycodestyle] Add blank line(s) rules (E301, E302, E303, E304, E305, E306)#8720hoel-bagard wants to merge 52 commits intoastral-sh:mainfrom
pycodestyle] Add blank line(s) rules (E301, E302, E303, E304, E305, E306)#8720Conversation
|
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| E302 | 2887 | 2887 | 0 | 0 | 0 |
| E305 | 388 | 388 | 0 | 0 | 0 |
| E301 | 270 | 270 | 0 | 0 | 0 |
| E306 | 265 | 265 | 0 | 0 | 0 |
| E303 | 74 | 74 | 0 | 0 | 0 |
| PLR0917 | 52 | 26 | 26 | 0 | 0 |
| E304 | 1 | 1 | 0 | 0 | 0 |
Formatter (stable)
✅ ecosystem check detected no format changes.
Formatter (preview)
✅ ecosystem check detected no format changes.
decorator -> comment -> decorator was causing a false positive.
Fix false positive where a method following an if (or other indentation inducing keyword) would trigger E301.
This also move the trigger on an async def from the def to the async.
14b784c to
0bf4c45
Compare
Make the comment stick to the following line instead of the preceding one.
|
With PyCQA/pycodestyle#1215 merged, the "top-levelness instead of class/def" approach now seems indisputably correct. |
21bd298 to
fd65c70
Compare
MichaReiser
left a comment
There was a problem hiding this comment.
Thanks for working on this (again).
I left a few comments on how I think the state could be simplified which should make it easier to reason about and review the code changes.
I still feel somewhat uncomfortable to integrate this into logical lines. Are there examples where it is important that the rule runs on logical lines? If so, then using logical lines is the right thing to do. If not, then it might be overkill and it might be easier to just copy over of what's needed from LogicalLine into a BlankLine checker.
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/blank_lines.rs
Outdated
Show resolved
Hide resolved
| Diagnostic::new(TooManyBlankLines(line.line.blank_lines), token.range); | ||
|
|
||
| let chars_to_remove = if indent_level > 0 { | ||
| line.line.preceding_blank_characters - BlankLinesConfig::METHOD |
There was a problem hiding this comment.
Would it be possible to compute the blank lines ad-hoc? Storing them for every line seems expensive, especially because they're only needed for fixes.
There was a problem hiding this comment.
There isn't a way to go back to previous logical lines, right ?
Then the only option (afaik) would be to work with text and to go back until finding the end of the previous non-blank line. My understanding is that it would be slow, however if that is run only for fixes, then maybe it's fine.
|
I guess I need to get a better understanding when this rule is supposed to run. What I'm wondering is if it is sufficient to only test for empty lines after each Newline (which indicates a new logical line) and use |
|
Thank you for your review. I don't know if using logical lines is required. I was under the impression that I could only use physical or logical lines, and with physical lines ruled out there was only logical lines left. As long as it's possible to check for indents/detents, def/async def, class and decorator tokens, I suppose it might be possible to not use logical lines. |
e335a5e to
304115a
Compare
…lank_lines.rs Co-authored-by: Micha Reiser <micha@reiser.io>
With BlankLinesChecker containing the method doing the checking.
|
The alternative is that you create a function similar to Do you want to play around with it to see how it feels? Feel free to publish it as a separate (or stacked) PR. I don't want that you have to undo the work if logical lines was the right place to begin with. See ruff/crates/ruff_linter/src/checkers/logical_lines.rs Lines 33 to 38 in c38617f |
|
Would the main goal be to not store the number of preceding blank lines/characters for each line ? |
The main goal is to understand if the rules fit into the logical lines or not. To me, it seems they don't really re-use the logic of logical lines, but it adds complexity to the logical line data structures (making it harder to understand and maintain). Meaning, the overall implementation may be more complicated than it has to. It also has the downside that running the logical line rules only (excluding blank lines) now pays for some of the blank line's runtime cost without using it. . |
|
Ok, I'll try to make the change. |
|
very happy to see E303 coming, thank you all! my ocd will thank you <3 |
|
As a note, autofixes for all these rules would cover |
|
@MichaReiser I've made a version that does not use logical lines here. Overall I feel like the added logic isn't too complex, especially since it removes some functions from the logical lines version. I still need to operate on logical lines (since pycodestyle did), so I'm still building them, but I only keep track of what I actually need. |
CodSpeed Performance ReportMerging #8720 will not alter performanceComparing Summary
|
Summary
This PR is part of #2402, it adds the
E301,E302,E303,E304,E305,E306error rules along with their fixes.A first attempt at implementing
E305using physical lines was done here, and a second attempt using logical lines here. This version uses the fact that comment only lines are now counted as logical lines.Test Plan
The test fixture uses the one from pycodestyle with a few added tests.