mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 22:31:47 +00:00
[pycodestyle
] Respect isort
settings in blank line rules (E3*
) (#10096)
## Summary This PR changes the `E3*` rules to respect the `isort` `lines-after-imports` and `lines-between-types` settings. Specifically, the following rules required changing * `TooManyBlannkLines` : Respects both settings. * `BlankLinesTopLevel`: Respects `lines-after-imports`. Doesn't need to respect `lines-between-types` because it only applies to classes and functions The downside of this approach is that `isort` and the blank line rules emit a diagnostic when there are too many blank lines. The fixes aren't identical, the blank line is less opinionated, but blank lines accepts the fix of `isort`. <details> <summary>Outdated approach</summary> Fixes https://github.com/astral-sh/ruff/issues/10077#issuecomment-1961266981 This PR changes the blank line rules to not enforce the number of blank lines after imports (top-level) if isort is enabled and leave it to isort to enforce the right number of lines (depends on the `isort.lines-after-imports` and `isort.lines-between-types` settings). The reason to give `isort` precedence over the blank line rules is that they are configurable. Users that always want to blank lines after imports can use `isort.lines-after-imports=2` to enforce that (specifically for imports). This PR does not fix the incompatibility with the formatter in pyi files that only uses 0 to 1 blank lines. I'll address this separately. </details> ## Review The first commit is a small refactor that simplified implementing the fix (and makes it easier to reason about what's mutable and what's not). ## Test Plan I added a new test and verified that it fails with an error that the fix never converges. I verified the snapshot output after implementing the fix. --------- Co-authored-by: Hoël Bagard <34478245+hoel-bagard@users.noreply.github.com>
This commit is contained in:
parent
d441338358
commit
46ab9dec18
16 changed files with 1601 additions and 284 deletions
8
crates/ruff_linter/resources/test/fixtures/pycodestyle/.editorconfig
vendored
Normal file
8
crates/ruff_linter/resources/test/fixtures/pycodestyle/.editorconfig
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
# These rules test for intentional "odd" formatting. Using a formatter fixes that
|
||||
[E{1,2,3}*.py]
|
||||
generated_code = true
|
||||
ij_formatter_enabled = false
|
||||
|
||||
[W*.py]
|
||||
generated_code = true
|
||||
ij_formatter_enabled = false
|
62
crates/ruff_linter/resources/test/fixtures/pycodestyle/E30_isort.py
vendored
Normal file
62
crates/ruff_linter/resources/test/fixtures/pycodestyle/E30_isort.py
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
import json
|
||||
|
||||
|
||||
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class MissingCommand(TypeError): ... # noqa: N818
|
||||
|
||||
|
||||
class BackendProxy:
|
||||
backend_module: str
|
||||
backend_object: str | None
|
||||
backend: Any
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import abcd
|
||||
|
||||
|
||||
abcd.foo()
|
||||
|
||||
def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import os
|
||||
|
||||
|
||||
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
|
||||
abcd.foo()
|
||||
|
||||
def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
...
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
...
|
||||
|
||||
|
||||
def _exit(self) -> None: ...
|
||||
|
||||
|
||||
def _optional_commands(self) -> dict[str, bool]: ...
|
||||
|
||||
|
||||
def run(argv: Sequence[str]) -> int: ...
|
||||
|
||||
|
||||
def read_line(fd: int = 0) -> bytearray: ...
|
||||
|
||||
|
||||
def flush() -> None: ...
|
||||
|
||||
|
||||
from typing import Any, Sequence
|
||||
|
||||
class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -41,14 +41,7 @@ pub(crate) fn check_tokens(
|
|||
Rule::BlankLinesAfterFunctionOrClass,
|
||||
Rule::BlankLinesBeforeNestedDefinition,
|
||||
]) {
|
||||
let mut blank_lines_checker = BlankLinesChecker::default();
|
||||
blank_lines_checker.check_lines(
|
||||
tokens,
|
||||
locator,
|
||||
stylist,
|
||||
settings.tab_size,
|
||||
&mut diagnostics,
|
||||
);
|
||||
BlankLinesChecker::new(locator, stylist, settings).check_lines(tokens, &mut diagnostics);
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::BlanketNOQA) {
|
||||
|
|
|
@ -16,7 +16,7 @@ mod tests {
|
|||
|
||||
use crate::line_width::LineLength;
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::pycodestyle;
|
||||
use crate::rules::{isort, pycodestyle};
|
||||
use crate::settings::types::PreviewMode;
|
||||
use crate::test::test_path;
|
||||
use crate::{assert_messages, settings};
|
||||
|
@ -138,14 +138,23 @@ mod tests {
|
|||
Path::new("E25.py")
|
||||
)]
|
||||
#[test_case(Rule::MissingWhitespaceAroundParameterEquals, Path::new("E25.py"))]
|
||||
fn logical(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
Path::new("pycodestyle").join(path).as_path(),
|
||||
&settings::LinterSettings::for_rule(rule_code),
|
||||
)?;
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::BlankLineBetweenMethods, Path::new("E30.py"))]
|
||||
#[test_case(Rule::BlankLinesTopLevel, Path::new("E30.py"))]
|
||||
#[test_case(Rule::TooManyBlankLines, Path::new("E30.py"))]
|
||||
#[test_case(Rule::BlankLineAfterDecorator, Path::new("E30.py"))]
|
||||
#[test_case(Rule::BlankLinesAfterFunctionOrClass, Path::new("E30.py"))]
|
||||
#[test_case(Rule::BlankLinesBeforeNestedDefinition, Path::new("E30.py"))]
|
||||
|
||||
fn logical(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
fn blank_lines(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
Path::new("pycodestyle").join(path).as_path(),
|
||||
|
@ -155,6 +164,64 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests the compatibility of the blank line top level rule and isort.
|
||||
#[test_case(-1, 0)]
|
||||
#[test_case(1, 1)]
|
||||
#[test_case(0, 0)]
|
||||
#[test_case(4, 4)]
|
||||
fn blank_lines_top_level_isort_compatibility(
|
||||
lines_after_imports: isize,
|
||||
lines_between_types: usize,
|
||||
) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"blank_lines_top_level_isort_compatibility-lines-after({lines_after_imports})-between({lines_between_types})"
|
||||
);
|
||||
let diagnostics = test_path(
|
||||
Path::new("pycodestyle").join("E30_isort.py"),
|
||||
&settings::LinterSettings {
|
||||
isort: isort::settings::Settings {
|
||||
lines_after_imports,
|
||||
lines_between_types,
|
||||
..isort::settings::Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rules([
|
||||
Rule::BlankLinesTopLevel,
|
||||
Rule::UnsortedImports,
|
||||
])
|
||||
},
|
||||
)?;
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests the compatibility of the blank line too many lines and isort.
|
||||
#[test_case(-1, 0)]
|
||||
#[test_case(1, 1)]
|
||||
#[test_case(0, 0)]
|
||||
#[test_case(4, 4)]
|
||||
fn too_many_blank_lines_isort_compatibility(
|
||||
lines_after_imports: isize,
|
||||
lines_between_types: usize,
|
||||
) -> Result<()> {
|
||||
let snapshot = format!("too_many_blank_lines_isort_compatibility-lines-after({lines_after_imports})-between({lines_between_types})");
|
||||
let diagnostics = test_path(
|
||||
Path::new("pycodestyle").join("E30_isort.py"),
|
||||
&settings::LinterSettings {
|
||||
isort: isort::settings::Settings {
|
||||
lines_after_imports,
|
||||
lines_between_types,
|
||||
..isort::settings::Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rules([
|
||||
Rule::TooManyBlankLines,
|
||||
Rule::UnsortedImports,
|
||||
])
|
||||
},
|
||||
)?;
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constant_literals() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
|
|
|
@ -24,7 +24,7 @@ use ruff_python_trivia::PythonWhitespace;
|
|||
/// Number of blank lines around top level classes and functions.
|
||||
const BLANK_LINES_TOP_LEVEL: u32 = 2;
|
||||
/// Number of blank lines around methods and nested classes and functions.
|
||||
const BLANK_LINES_METHOD_LEVEL: u32 = 1;
|
||||
const BLANK_LINES_NESTED_LEVEL: u32 = 1;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for missing blank lines between methods of a class.
|
||||
|
@ -60,7 +60,7 @@ pub struct BlankLineBetweenMethods;
|
|||
impl AlwaysFixableViolation for BlankLineBetweenMethods {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Expected {BLANK_LINES_METHOD_LEVEL:?} blank line, found 0")
|
||||
format!("Expected {BLANK_LINES_NESTED_LEVEL:?} blank line, found 0")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
|
@ -74,6 +74,10 @@ impl AlwaysFixableViolation for BlankLineBetweenMethods {
|
|||
/// ## Why is this bad?
|
||||
/// PEP 8 recommends exactly two blank lines between top level functions and classes.
|
||||
///
|
||||
/// Note: The rule respects the [`lint.isort.lines-after-imports`] setting when determining
|
||||
/// the required number of blank lines between top-level `import` statements and function or class definitions
|
||||
/// for compatibility with isort.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def func1():
|
||||
|
@ -98,16 +102,18 @@ impl AlwaysFixableViolation for BlankLineBetweenMethods {
|
|||
#[violation]
|
||||
pub struct BlankLinesTopLevel {
|
||||
actual_blank_lines: u32,
|
||||
expected_blank_lines: u32,
|
||||
}
|
||||
|
||||
impl AlwaysFixableViolation for BlankLinesTopLevel {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let BlankLinesTopLevel {
|
||||
actual_blank_lines: nb_blank_lines,
|
||||
actual_blank_lines,
|
||||
expected_blank_lines,
|
||||
} = self;
|
||||
|
||||
format!("Expected {BLANK_LINES_TOP_LEVEL:?} blank lines, found {nb_blank_lines}")
|
||||
format!("Expected {expected_blank_lines:?} blank lines, found {actual_blank_lines}")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
|
@ -144,6 +150,10 @@ impl AlwaysFixableViolation for BlankLinesTopLevel {
|
|||
/// pass
|
||||
/// ```
|
||||
///
|
||||
/// Note: The rule respects the following `isort` settings when determining the maximum number of blank lines allowed between two statements:
|
||||
/// * [`lint.isort.lines-after-imports`]: For top-level statements directly following an import statement.
|
||||
/// * [`lint.isort.lines-between-types`]: For `import` statements directly following a `from ... import ...` statement or vice versa.
|
||||
///
|
||||
/// ## References
|
||||
/// - [PEP 8](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E303.html)
|
||||
|
@ -155,10 +165,9 @@ pub struct TooManyBlankLines {
|
|||
impl AlwaysFixableViolation for TooManyBlankLines {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let TooManyBlankLines {
|
||||
actual_blank_lines: nb_blank_lines,
|
||||
} = self;
|
||||
format!("Too many blank lines ({nb_blank_lines})")
|
||||
let TooManyBlankLines { actual_blank_lines } = self;
|
||||
|
||||
format!("Too many blank lines ({actual_blank_lines})")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
|
@ -415,6 +424,8 @@ impl<'a> Iterator for LinePreprocessor<'a> {
|
|||
{
|
||||
LogicalLineKind::Function
|
||||
}
|
||||
TokenKind::Import => LogicalLineKind::Import,
|
||||
TokenKind::From => LogicalLineKind::FromImport,
|
||||
_ => LogicalLineKind::Other,
|
||||
};
|
||||
|
||||
|
@ -560,9 +571,17 @@ enum Follows {
|
|||
Other,
|
||||
Decorator,
|
||||
Def,
|
||||
Import,
|
||||
FromImport,
|
||||
Docstring,
|
||||
}
|
||||
|
||||
impl Follows {
|
||||
const fn is_any_import(self) -> bool {
|
||||
matches!(self, Follows::Import | Follows::FromImport)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
enum Status {
|
||||
/// Stores the indent level where the nesting started.
|
||||
|
@ -602,40 +621,99 @@ impl Status {
|
|||
}
|
||||
|
||||
/// Contains variables used for the linting of blank lines.
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct BlankLinesChecker {
|
||||
follows: Follows,
|
||||
fn_status: Status,
|
||||
class_status: Status,
|
||||
/// First line that is not a comment.
|
||||
is_not_first_logical_line: bool,
|
||||
/// Used for the fix in case a comment separates two non-comment logical lines to make the comment "stick"
|
||||
/// to the second line instead of the first.
|
||||
last_non_comment_line_end: TextSize,
|
||||
previous_unindented_line_kind: Option<LogicalLineKind>,
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct BlankLinesChecker<'a> {
|
||||
stylist: &'a Stylist<'a>,
|
||||
locator: &'a Locator<'a>,
|
||||
indent_width: IndentWidth,
|
||||
lines_after_imports: isize,
|
||||
lines_between_types: usize,
|
||||
}
|
||||
|
||||
impl BlankLinesChecker {
|
||||
impl<'a> BlankLinesChecker<'a> {
|
||||
pub(crate) fn new(
|
||||
locator: &'a Locator<'a>,
|
||||
stylist: &'a Stylist<'a>,
|
||||
settings: &crate::settings::LinterSettings,
|
||||
) -> BlankLinesChecker<'a> {
|
||||
BlankLinesChecker {
|
||||
stylist,
|
||||
locator,
|
||||
indent_width: settings.tab_size,
|
||||
lines_after_imports: settings.isort.lines_after_imports,
|
||||
lines_between_types: settings.isort.lines_between_types,
|
||||
}
|
||||
}
|
||||
|
||||
/// E301, E302, E303, E304, E305, E306
|
||||
pub(crate) fn check_lines(
|
||||
&mut self,
|
||||
tokens: &[LexResult],
|
||||
locator: &Locator,
|
||||
stylist: &Stylist,
|
||||
indent_width: IndentWidth,
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
pub(crate) fn check_lines(&self, tokens: &[LexResult], diagnostics: &mut Vec<Diagnostic>) {
|
||||
let mut prev_indent_length: Option<usize> = None;
|
||||
let line_preprocessor = LinePreprocessor::new(tokens, locator, indent_width);
|
||||
let mut state = BlankLinesState::default();
|
||||
let line_preprocessor = LinePreprocessor::new(tokens, self.locator, self.indent_width);
|
||||
|
||||
for logical_line in line_preprocessor {
|
||||
self.check_line(
|
||||
&logical_line,
|
||||
prev_indent_length,
|
||||
locator,
|
||||
stylist,
|
||||
diagnostics,
|
||||
);
|
||||
// Reset `follows` after a dedent:
|
||||
// ```python
|
||||
// if True:
|
||||
// import test
|
||||
// a = 10
|
||||
// ```
|
||||
// The `a` statement doesn't follow the `import` statement but the `if` statement.
|
||||
if let Some(prev_indent_length) = prev_indent_length {
|
||||
if prev_indent_length > logical_line.indent_length {
|
||||
state.follows = Follows::Other;
|
||||
}
|
||||
}
|
||||
|
||||
state.class_status.update(&logical_line);
|
||||
state.fn_status.update(&logical_line);
|
||||
|
||||
if state.is_not_first_logical_line {
|
||||
self.check_line(&logical_line, &state, prev_indent_length, diagnostics);
|
||||
}
|
||||
|
||||
match logical_line.kind {
|
||||
LogicalLineKind::Class => {
|
||||
if matches!(state.class_status, Status::Outside) {
|
||||
state.class_status = Status::Inside(logical_line.indent_length);
|
||||
}
|
||||
state.follows = Follows::Other;
|
||||
}
|
||||
LogicalLineKind::Decorator => {
|
||||
state.follows = Follows::Decorator;
|
||||
}
|
||||
LogicalLineKind::Function => {
|
||||
if matches!(state.fn_status, Status::Outside) {
|
||||
state.fn_status = Status::Inside(logical_line.indent_length);
|
||||
}
|
||||
state.follows = Follows::Def;
|
||||
}
|
||||
LogicalLineKind::Comment => {}
|
||||
LogicalLineKind::Import => {
|
||||
state.follows = Follows::Import;
|
||||
}
|
||||
LogicalLineKind::FromImport => {
|
||||
state.follows = Follows::FromImport;
|
||||
}
|
||||
LogicalLineKind::Other => {
|
||||
state.follows = Follows::Other;
|
||||
}
|
||||
}
|
||||
|
||||
if logical_line.is_docstring {
|
||||
state.follows = Follows::Docstring;
|
||||
}
|
||||
|
||||
if !logical_line.is_comment_only {
|
||||
state.is_not_first_logical_line = true;
|
||||
|
||||
state.last_non_comment_line_end = logical_line.logical_line_end;
|
||||
|
||||
if logical_line.indent_length == 0 {
|
||||
state.previous_unindented_line_kind = Some(logical_line.kind);
|
||||
}
|
||||
}
|
||||
|
||||
if !logical_line.is_comment_only {
|
||||
prev_indent_length = Some(logical_line.indent_length);
|
||||
}
|
||||
|
@ -644,81 +722,109 @@ impl BlankLinesChecker {
|
|||
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
fn check_line(
|
||||
&mut self,
|
||||
&self,
|
||||
line: &LogicalLineInfo,
|
||||
state: &BlankLinesState,
|
||||
prev_indent_length: Option<usize>,
|
||||
locator: &Locator,
|
||||
stylist: &Stylist,
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
self.class_status.update(line);
|
||||
self.fn_status.update(line);
|
||||
|
||||
// Don't expect blank lines before the first non comment line.
|
||||
if self.is_not_first_logical_line {
|
||||
if line.preceding_blank_lines == 0
|
||||
// Only applies to methods.
|
||||
&& matches!(line.kind, LogicalLineKind::Function | LogicalLineKind::Decorator)
|
||||
// Allow groups of one-liners.
|
||||
&& !(matches!(self.follows, Follows::Def) && !matches!(line.last_token, TokenKind::Colon))
|
||||
&& matches!(self.class_status, Status::Inside(_))
|
||||
&& !(matches!(state.follows, Follows::Def) && !matches!(line.last_token, TokenKind::Colon))
|
||||
&& matches!(state.class_status, Status::Inside(_))
|
||||
// The class/parent method's docstring can directly precede the def.
|
||||
// Allow following a decorator (if there is an error it will be triggered on the first decorator).
|
||||
&& !matches!(self.follows, Follows::Docstring | Follows::Decorator)
|
||||
&& !matches!(state.follows, Follows::Docstring | Follows::Decorator)
|
||||
// Do not trigger when the def follows an if/while/etc...
|
||||
&& prev_indent_length.is_some_and(|prev_indent_length| prev_indent_length >= line.indent_length)
|
||||
{
|
||||
// E301
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(BlankLineBetweenMethods, line.first_token_range);
|
||||
let mut diagnostic = Diagnostic::new(BlankLineBetweenMethods, line.first_token_range);
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
stylist.line_ending().to_string(),
|
||||
locator.line_start(self.last_non_comment_line_end),
|
||||
self.stylist.line_ending().to_string(),
|
||||
self.locator.line_start(state.last_non_comment_line_end),
|
||||
)));
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
if line.preceding_blank_lines < BLANK_LINES_TOP_LEVEL
|
||||
let expected_blank_lines_before_definition = if line.indent_length == 0 {
|
||||
// Mimic the isort rules for the number of blank lines before classes and functions
|
||||
if state.follows.is_any_import() {
|
||||
// Fallback to the default if the value is too large for an u32 or if it is negative.
|
||||
// A negative value means that isort should determine the blank lines automatically.
|
||||
// `isort` defaults to 2 if before a class or function definition and 1 otherwise.
|
||||
// Defaulting to 2 here is correct because the variable is only used when testing the
|
||||
// blank lines before a class or function definition.
|
||||
u32::try_from(self.lines_after_imports).unwrap_or(BLANK_LINES_TOP_LEVEL)
|
||||
} else {
|
||||
BLANK_LINES_TOP_LEVEL
|
||||
}
|
||||
} else {
|
||||
BLANK_LINES_NESTED_LEVEL
|
||||
};
|
||||
|
||||
if line.preceding_blank_lines < expected_blank_lines_before_definition
|
||||
// Allow following a decorator (if there is an error it will be triggered on the first decorator).
|
||||
&& !matches!(self.follows, Follows::Decorator)
|
||||
&& !matches!(state.follows, Follows::Decorator)
|
||||
// Allow groups of one-liners.
|
||||
&& !(matches!(self.follows, Follows::Def) && !matches!(line.last_token, TokenKind::Colon))
|
||||
&& !(matches!(state.follows, Follows::Def) && !matches!(line.last_token, TokenKind::Colon))
|
||||
// Only trigger on non-indented classes and functions (for example functions within an if are ignored)
|
||||
&& line.indent_length == 0
|
||||
// Only apply to functions or classes.
|
||||
&& line.kind.is_top_level()
|
||||
&& line.kind.is_class_function_or_decorator()
|
||||
{
|
||||
// E302
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
BlankLinesTopLevel {
|
||||
actual_blank_lines: line.preceding_blank_lines.count(),
|
||||
expected_blank_lines: expected_blank_lines_before_definition,
|
||||
},
|
||||
line.first_token_range,
|
||||
);
|
||||
|
||||
if let Some(blank_lines_range) = line.blank_lines.range() {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
|
||||
stylist.line_ending().repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
self.stylist
|
||||
.line_ending()
|
||||
.repeat(expected_blank_lines_before_definition as usize),
|
||||
blank_lines_range,
|
||||
)));
|
||||
} else {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
stylist.line_ending().repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
locator.line_start(self.last_non_comment_line_end),
|
||||
self.stylist
|
||||
.line_ending()
|
||||
.repeat(expected_blank_lines_before_definition as usize),
|
||||
self.locator.line_start(state.last_non_comment_line_end),
|
||||
)));
|
||||
}
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
let expected_blank_lines = if line.indent_length > 0 {
|
||||
BLANK_LINES_METHOD_LEVEL
|
||||
} else {
|
||||
let max_lines_level = if line.indent_length == 0 {
|
||||
BLANK_LINES_TOP_LEVEL
|
||||
} else {
|
||||
BLANK_LINES_NESTED_LEVEL
|
||||
};
|
||||
|
||||
if line.blank_lines > expected_blank_lines {
|
||||
// If between `import` and `from .. import ..` or the other way round,
|
||||
// allow up to `lines_between_types` newlines for isort compatibility.
|
||||
// We let `isort` remove extra blank lines when the imports belong
|
||||
// to different sections.
|
||||
let max_blank_lines = if matches!(
|
||||
(line.kind, state.follows),
|
||||
(LogicalLineKind::Import, Follows::FromImport)
|
||||
| (LogicalLineKind::FromImport, Follows::Import)
|
||||
) {
|
||||
max_lines_level.max(u32::try_from(self.lines_between_types).unwrap_or(u32::MAX))
|
||||
} else {
|
||||
expected_blank_lines_before_definition
|
||||
};
|
||||
|
||||
if line.blank_lines > max_blank_lines {
|
||||
// E303
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
TooManyBlankLines {
|
||||
|
@ -728,16 +834,20 @@ impl BlankLinesChecker {
|
|||
);
|
||||
|
||||
if let Some(blank_lines_range) = line.blank_lines.range() {
|
||||
if max_blank_lines == 0 {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(blank_lines_range)));
|
||||
} else {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
|
||||
stylist.line_ending().repeat(expected_blank_lines as usize),
|
||||
self.stylist.line_ending().repeat(max_blank_lines as usize),
|
||||
blank_lines_range,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
if matches!(self.follows, Follows::Decorator)
|
||||
if matches!(state.follows, Follows::Decorator)
|
||||
&& !line.is_comment_only
|
||||
&& line.preceding_blank_lines > 0
|
||||
{
|
||||
|
@ -752,21 +862,19 @@ impl BlankLinesChecker {
|
|||
// Get all the lines between the last decorator line (included) and the current line (included).
|
||||
// Then remove all blank lines.
|
||||
let trivia_range = TextRange::new(
|
||||
self.last_non_comment_line_end,
|
||||
locator.line_start(line.first_token_range.start()),
|
||||
state.last_non_comment_line_end,
|
||||
self.locator.line_start(line.first_token_range.start()),
|
||||
);
|
||||
let trivia_text = locator.slice(trivia_range);
|
||||
let trivia_text = self.locator.slice(trivia_range);
|
||||
let mut trivia_without_blank_lines = trivia_text
|
||||
.universal_newlines()
|
||||
.filter_map(|line| {
|
||||
(!line.trim_whitespace().is_empty()).then_some(line.as_str())
|
||||
})
|
||||
.join(&stylist.line_ending());
|
||||
.filter_map(|line| (!line.trim_whitespace().is_empty()).then_some(line.as_str()))
|
||||
.join(&self.stylist.line_ending());
|
||||
|
||||
let fix = if trivia_without_blank_lines.is_empty() {
|
||||
Fix::safe_edit(Edit::range_deletion(trivia_range))
|
||||
} else {
|
||||
trivia_without_blank_lines.push_str(&stylist.line_ending());
|
||||
trivia_without_blank_lines.push_str(&self.stylist.line_ending());
|
||||
Fix::safe_edit(Edit::range_replacement(
|
||||
trivia_without_blank_lines,
|
||||
trivia_range,
|
||||
|
@ -779,12 +887,12 @@ impl BlankLinesChecker {
|
|||
}
|
||||
|
||||
if line.preceding_blank_lines < BLANK_LINES_TOP_LEVEL
|
||||
&& self
|
||||
&& state
|
||||
.previous_unindented_line_kind
|
||||
.is_some_and(LogicalLineKind::is_top_level)
|
||||
.is_some_and(LogicalLineKind::is_class_function_or_decorator)
|
||||
&& line.indent_length == 0
|
||||
&& !line.is_comment_only
|
||||
&& !line.kind.is_top_level()
|
||||
&& !line.kind.is_class_function_or_decorator()
|
||||
{
|
||||
// E305
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
|
@ -796,13 +904,17 @@ impl BlankLinesChecker {
|
|||
|
||||
if let Some(blank_lines_range) = line.blank_lines.range() {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
|
||||
stylist.line_ending().repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
self.stylist
|
||||
.line_ending()
|
||||
.repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
blank_lines_range,
|
||||
)));
|
||||
} else {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
stylist.line_ending().repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
locator.line_start(line.first_token_range.start()),
|
||||
self.stylist
|
||||
.line_ending()
|
||||
.repeat(BLANK_LINES_TOP_LEVEL as usize),
|
||||
self.locator.line_start(line.first_token_range.start()),
|
||||
)));
|
||||
}
|
||||
|
||||
|
@ -811,66 +923,42 @@ impl BlankLinesChecker {
|
|||
|
||||
if line.preceding_blank_lines == 0
|
||||
// Only apply to nested functions.
|
||||
&& matches!(self.fn_status, Status::Inside(_))
|
||||
&& line.kind.is_top_level()
|
||||
&& matches!(state.fn_status, Status::Inside(_))
|
||||
&& line.kind.is_class_function_or_decorator()
|
||||
// Allow following a decorator (if there is an error it will be triggered on the first decorator).
|
||||
&& !matches!(self.follows, Follows::Decorator)
|
||||
&& !matches!(state.follows, Follows::Decorator)
|
||||
// The class's docstring can directly precede the first function.
|
||||
&& !matches!(self.follows, Follows::Docstring)
|
||||
&& !matches!(state.follows, Follows::Docstring)
|
||||
// Do not trigger when the def/class follows an "indenting token" (if/while/etc...).
|
||||
&& prev_indent_length.is_some_and(|prev_indent_length| prev_indent_length >= line.indent_length)
|
||||
// Allow groups of one-liners.
|
||||
&& !(matches!(self.follows, Follows::Def) && line.last_token != TokenKind::Colon)
|
||||
&& !(matches!(state.follows, Follows::Def) && line.last_token != TokenKind::Colon)
|
||||
{
|
||||
// E306
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(BlankLinesBeforeNestedDefinition, line.first_token_range);
|
||||
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
stylist.line_ending().to_string(),
|
||||
locator.line_start(line.first_token_range.start()),
|
||||
self.stylist.line_ending().to_string(),
|
||||
self.locator.line_start(line.first_token_range.start()),
|
||||
)));
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match line.kind {
|
||||
LogicalLineKind::Class => {
|
||||
if matches!(self.class_status, Status::Outside) {
|
||||
self.class_status = Status::Inside(line.indent_length);
|
||||
}
|
||||
self.follows = Follows::Other;
|
||||
}
|
||||
LogicalLineKind::Decorator => {
|
||||
self.follows = Follows::Decorator;
|
||||
}
|
||||
LogicalLineKind::Function => {
|
||||
if matches!(self.fn_status, Status::Outside) {
|
||||
self.fn_status = Status::Inside(line.indent_length);
|
||||
}
|
||||
self.follows = Follows::Def;
|
||||
}
|
||||
LogicalLineKind::Comment => {}
|
||||
LogicalLineKind::Other => {
|
||||
self.follows = Follows::Other;
|
||||
}
|
||||
}
|
||||
|
||||
if line.is_docstring {
|
||||
self.follows = Follows::Docstring;
|
||||
}
|
||||
|
||||
if !line.is_comment_only {
|
||||
self.is_not_first_logical_line = true;
|
||||
|
||||
self.last_non_comment_line_end = line.logical_line_end;
|
||||
|
||||
if line.indent_length == 0 {
|
||||
self.previous_unindented_line_kind = Some(line.kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct BlankLinesState {
|
||||
follows: Follows,
|
||||
fn_status: Status,
|
||||
class_status: Status,
|
||||
/// First line that is not a comment.
|
||||
is_not_first_logical_line: bool,
|
||||
/// Used for the fix in case a comment separates two non-comment logical lines to make the comment "stick"
|
||||
/// to the second line instead of the first.
|
||||
last_non_comment_line_end: TextSize,
|
||||
previous_unindented_line_kind: Option<LogicalLineKind>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -883,12 +971,16 @@ enum LogicalLineKind {
|
|||
Function,
|
||||
/// A comment only line
|
||||
Comment,
|
||||
/// An import statement
|
||||
Import,
|
||||
/// A from.. import statement
|
||||
FromImport,
|
||||
/// Any other statement or clause header
|
||||
Other,
|
||||
}
|
||||
|
||||
impl LogicalLineKind {
|
||||
fn is_top_level(self) -> bool {
|
||||
fn is_class_function_or_decorator(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
LogicalLineKind::Class | LogicalLineKind::Function | LogicalLineKind::Decorator
|
||||
|
|
|
@ -246,5 +246,3 @@ E30.py:702:5: E303 [*] Too many blank lines (2)
|
|||
702 701 | pass
|
||||
703 702 | # end
|
||||
704 703 |
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 |-
|
||||
3 |-
|
||||
4 |-
|
||||
5 2 | from typing import Any, Sequence
|
||||
6 3 |
|
||||
7 4 |
|
||||
|
||||
E30_isort.py:23:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
21 | abcd.foo()
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
| ^^^ E302
|
||||
24 |
|
||||
25 | if TYPE_CHECKING:
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 |
|
||||
21 21 | abcd.foo()
|
||||
22 22 |
|
||||
23 |+
|
||||
23 24 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
24 25 |
|
||||
25 26 | if TYPE_CHECKING:
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:35:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
33 | abcd.foo()
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
36 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
32 32 |
|
||||
33 33 | abcd.foo()
|
||||
34 34 |
|
||||
35 |+
|
||||
35 36 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
36 37 | ...
|
||||
37 38 |
|
||||
|
||||
E30_isort.py:41:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
39 | from typing_extensions import TypeAlias
|
||||
40 |
|
||||
41 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
42 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
38 38 | if TYPE_CHECKING:
|
||||
39 39 | from typing_extensions import TypeAlias
|
||||
40 40 |
|
||||
41 |+
|
||||
41 42 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
42 43 | ...
|
||||
43 44 |
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
62 63 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
|
||||
E30_isort.py:62:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
60 | from typing import Any, Sequence
|
||||
61 |
|
||||
62 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E302
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
62 63 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 |-
|
||||
3 |-
|
||||
4 |-
|
||||
5 2 | from typing import Any, Sequence
|
||||
6 |-
|
||||
7 |-
|
||||
8 3 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 4 |
|
||||
10 5 |
|
||||
|
||||
E30_isort.py:23:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
21 | abcd.foo()
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
| ^^^ E302
|
||||
24 |
|
||||
25 | if TYPE_CHECKING:
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 |
|
||||
21 21 | abcd.foo()
|
||||
22 22 |
|
||||
23 |+
|
||||
23 24 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
24 25 |
|
||||
25 26 | if TYPE_CHECKING:
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:35:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
33 | abcd.foo()
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
36 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
32 32 |
|
||||
33 33 | abcd.foo()
|
||||
34 34 |
|
||||
35 |+
|
||||
35 36 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
36 37 | ...
|
||||
37 38 |
|
||||
|
||||
E30_isort.py:41:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
39 | from typing_extensions import TypeAlias
|
||||
40 |
|
||||
41 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
42 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
38 38 | if TYPE_CHECKING:
|
||||
39 39 | from typing_extensions import TypeAlias
|
||||
40 40 |
|
||||
41 |+
|
||||
41 42 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
42 43 | ...
|
||||
43 44 |
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
58 58 |
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 |-
|
||||
62 61 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 2 |
|
||||
3 |-
|
||||
4 |-
|
||||
5 3 | from typing import Any, Sequence
|
||||
6 |-
|
||||
7 4 |
|
||||
8 5 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 6 |
|
||||
|
||||
E30_isort.py:23:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
21 | abcd.foo()
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
| ^^^ E302
|
||||
24 |
|
||||
25 | if TYPE_CHECKING:
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 |
|
||||
21 21 | abcd.foo()
|
||||
22 22 |
|
||||
23 |+
|
||||
23 24 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
24 25 |
|
||||
25 26 | if TYPE_CHECKING:
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:35:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
33 | abcd.foo()
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
36 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
32 32 |
|
||||
33 33 | abcd.foo()
|
||||
34 34 |
|
||||
35 |+
|
||||
35 36 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
36 37 | ...
|
||||
37 38 |
|
||||
|
||||
E30_isort.py:41:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
39 | from typing_extensions import TypeAlias
|
||||
40 |
|
||||
41 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
42 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
38 38 | if TYPE_CHECKING:
|
||||
39 39 | from typing_extensions import TypeAlias
|
||||
40 40 |
|
||||
41 |+
|
||||
41 42 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
42 43 | ...
|
||||
43 44 |
|
|
@ -0,0 +1,166 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 |
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 |+
|
||||
5 6 | from typing import Any, Sequence
|
||||
6 7 |
|
||||
7 8 |
|
||||
9 |+
|
||||
10 |+
|
||||
8 11 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 12 |
|
||||
10 13 |
|
||||
|
||||
E30_isort.py:8:1: E302 [*] Expected 4 blank lines, found 2
|
||||
|
|
||||
8 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E302
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
5 5 | from typing import Any, Sequence
|
||||
6 6 |
|
||||
7 7 |
|
||||
8 |+
|
||||
9 |+
|
||||
8 10 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 11 |
|
||||
10 12 |
|
||||
|
||||
E30_isort.py:23:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
21 | abcd.foo()
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
| ^^^ E302
|
||||
24 |
|
||||
25 | if TYPE_CHECKING:
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 |
|
||||
21 21 | abcd.foo()
|
||||
22 22 |
|
||||
23 |+
|
||||
23 24 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
24 25 |
|
||||
25 26 | if TYPE_CHECKING:
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:35:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
33 | abcd.foo()
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
36 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
32 32 |
|
||||
33 33 | abcd.foo()
|
||||
34 34 |
|
||||
35 |+
|
||||
35 36 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
36 37 | ...
|
||||
37 38 |
|
||||
|
||||
E30_isort.py:41:1: E302 [*] Expected 2 blank lines, found 1
|
||||
|
|
||||
39 | from typing_extensions import TypeAlias
|
||||
40 |
|
||||
41 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
| ^^^ E302
|
||||
42 | ...
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
38 38 | if TYPE_CHECKING:
|
||||
39 39 | from typing_extensions import TypeAlias
|
||||
40 40 |
|
||||
41 |+
|
||||
41 42 | def __call__2(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
42 43 | ...
|
||||
43 44 |
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
63 |+
|
||||
64 |+
|
||||
62 65 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
|
||||
E30_isort.py:62:1: E302 [*] Expected 4 blank lines, found 1
|
||||
|
|
||||
60 | from typing import Any, Sequence
|
||||
61 |
|
||||
62 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E302
|
||||
|
|
||||
= help: Add missing blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
63 |+
|
||||
64 |+
|
||||
62 65 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 |-
|
||||
3 |-
|
||||
4 |-
|
||||
5 2 | from typing import Any, Sequence
|
||||
6 3 |
|
||||
7 4 |
|
||||
|
||||
E30_isort.py:5:1: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
5 | from typing import Any, Sequence
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 2 |
|
||||
3 3 |
|
||||
4 |-
|
||||
5 4 | from typing import Any, Sequence
|
||||
6 5 |
|
||||
7 6 |
|
||||
|
||||
E30_isort.py:21:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
21 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | if __name__ == "__main__":
|
||||
18 18 | import abcd
|
||||
19 19 |
|
||||
20 |-
|
||||
21 20 | abcd.foo()
|
||||
22 21 |
|
||||
23 22 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:30:5: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
30 | from typing_extensions import TypeAlias
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:33:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
33 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 |
|
||||
30 30 | from typing_extensions import TypeAlias
|
||||
31 31 |
|
||||
32 |-
|
||||
33 32 | abcd.foo()
|
||||
34 33 |
|
||||
35 34 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
62 63 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -0,0 +1,171 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 |-
|
||||
3 |-
|
||||
4 |-
|
||||
5 2 | from typing import Any, Sequence
|
||||
6 |-
|
||||
7 |-
|
||||
8 3 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 4 |
|
||||
10 5 |
|
||||
|
||||
E30_isort.py:5:1: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
5 | from typing import Any, Sequence
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 2 |
|
||||
3 3 |
|
||||
4 |-
|
||||
5 4 | from typing import Any, Sequence
|
||||
6 5 |
|
||||
7 6 |
|
||||
|
||||
E30_isort.py:8:1: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
8 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 5 | from typing import Any, Sequence
|
||||
6 |-
|
||||
7 |-
|
||||
8 6 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 7 |
|
||||
10 8 |
|
||||
|
||||
E30_isort.py:21:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
21 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | if __name__ == "__main__":
|
||||
18 18 | import abcd
|
||||
19 19 |
|
||||
20 |-
|
||||
21 20 | abcd.foo()
|
||||
22 21 |
|
||||
23 22 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:30:5: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
30 | from typing_extensions import TypeAlias
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:33:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
33 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 |
|
||||
30 30 | from typing_extensions import TypeAlias
|
||||
31 31 |
|
||||
32 |-
|
||||
33 32 | abcd.foo()
|
||||
34 33 |
|
||||
35 34 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
58 58 |
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 |-
|
||||
62 61 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
|
||||
E30_isort.py:62:1: E303 [*] Too many blank lines (1)
|
||||
|
|
||||
60 | from typing import Any, Sequence
|
||||
61 |
|
||||
62 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
58 58 |
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 |-
|
||||
62 61 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 2 |
|
||||
3 |-
|
||||
4 |-
|
||||
5 3 | from typing import Any, Sequence
|
||||
6 |-
|
||||
7 4 |
|
||||
8 5 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 6 |
|
||||
|
||||
E30_isort.py:5:1: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
5 | from typing import Any, Sequence
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import json
|
||||
2 2 |
|
||||
3 3 |
|
||||
4 |-
|
||||
5 4 | from typing import Any, Sequence
|
||||
6 5 |
|
||||
7 6 |
|
||||
|
||||
E30_isort.py:8:1: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
8 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| ^^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
4 4 |
|
||||
5 5 | from typing import Any, Sequence
|
||||
6 6 |
|
||||
7 |-
|
||||
8 7 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 8 |
|
||||
10 9 |
|
||||
|
||||
E30_isort.py:21:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
21 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | if __name__ == "__main__":
|
||||
18 18 | import abcd
|
||||
19 19 |
|
||||
20 |-
|
||||
21 20 | abcd.foo()
|
||||
22 21 |
|
||||
23 22 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:30:5: E303 [*] Too many blank lines (3)
|
||||
|
|
||||
30 | from typing_extensions import TypeAlias
|
||||
| ^^^^ E303
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:33:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
33 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 |
|
||||
30 30 | from typing_extensions import TypeAlias
|
||||
31 31 |
|
||||
32 |-
|
||||
33 32 | abcd.foo()
|
||||
34 33 |
|
||||
35 34 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E30_isort.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
1 | / import json
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | | from typing import Any, Sequence
|
||||
6 | |
|
||||
7 | |
|
||||
8 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 |
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 |+
|
||||
5 6 | from typing import Any, Sequence
|
||||
6 7 |
|
||||
7 8 |
|
||||
9 |+
|
||||
10 |+
|
||||
8 11 | class MissingCommand(TypeError): ... # noqa: N818
|
||||
9 12 |
|
||||
10 13 |
|
||||
|
||||
E30_isort.py:21:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
21 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
22 |
|
||||
23 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | if __name__ == "__main__":
|
||||
18 18 | import abcd
|
||||
19 19 |
|
||||
20 |-
|
||||
21 20 | abcd.foo()
|
||||
22 21 |
|
||||
23 22 | def __init__(self, backend_module: str, backend_obj: str | None) -> None: ...
|
||||
|
||||
E30_isort.py:26:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
25 | if TYPE_CHECKING:
|
||||
26 | / import os
|
||||
27 | |
|
||||
28 | |
|
||||
29 | |
|
||||
30 | | from typing_extensions import TypeAlias
|
||||
31 | |
|
||||
| |_^ I001
|
||||
32 |
|
||||
33 | abcd.foo()
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
25 25 | if TYPE_CHECKING:
|
||||
26 26 | import os
|
||||
27 27 |
|
||||
28 |-
|
||||
29 |-
|
||||
30 28 | from typing_extensions import TypeAlias
|
||||
31 29 |
|
||||
32 30 |
|
||||
|
||||
E30_isort.py:33:5: E303 [*] Too many blank lines (2)
|
||||
|
|
||||
33 | abcd.foo()
|
||||
| ^^^^ E303
|
||||
34 |
|
||||
35 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
|
||||
= help: Remove extraneous blank line(s)
|
||||
|
||||
ℹ Safe fix
|
||||
29 29 |
|
||||
30 30 | from typing_extensions import TypeAlias
|
||||
31 31 |
|
||||
32 |-
|
||||
33 32 | abcd.foo()
|
||||
34 33 |
|
||||
35 34 | def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
||||
|
||||
E30_isort.py:60:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
|
|
||||
60 | / from typing import Any, Sequence
|
||||
61 | |
|
||||
62 | | class MissingCommand(TypeError): ... # noqa: N818
|
||||
| |_^ I001
|
||||
|
|
||||
= help: Organize imports
|
||||
|
||||
ℹ Safe fix
|
||||
59 59 |
|
||||
60 60 | from typing import Any, Sequence
|
||||
61 61 |
|
||||
62 |+
|
||||
63 |+
|
||||
64 |+
|
||||
62 65 | class MissingCommand(TypeError): ... # noqa: N818
|
|
@ -12,6 +12,7 @@ use ruff_source_file::{find_newline, LineEnding};
|
|||
use ruff_python_ast::str::leading_quote;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Stylist<'a> {
|
||||
locator: &'a Locator<'a>,
|
||||
indentation: Indentation,
|
||||
|
@ -145,7 +146,7 @@ impl fmt::Display for Quote {
|
|||
}
|
||||
|
||||
/// The indentation style used in Python source code.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Indentation(String);
|
||||
|
||||
impl Indentation {
|
||||
|
|
|
@ -9,6 +9,7 @@ use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
|||
use crate::newlines::find_newline;
|
||||
use crate::{LineIndex, OneIndexed, SourceCode, SourceLocation};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Locator<'a> {
|
||||
contents: &'a str,
|
||||
index: OnceCell<LineIndex>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue