Compare commits

...

3 Commits

Author SHA1 Message Date
Micha Reiser
ee7294e556 Split over-long comprehensions after in 2024-08-15 18:31:59 +02:00
Jonathan Plasse
52d27befe8 Rename too-many-positional(-arguments) (#12905) 2024-08-15 18:13:25 +02:00
Alex Waygood
6ed06afd28 Fixup description of default values for fixture-parentheses and mark-parentheses (#12904) 2024-08-15 15:20:36 +01:00
15 changed files with 105 additions and 76 deletions

View File

@@ -263,8 +263,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
if checker.enabled(Rule::TooManyArguments) {
pylint::rules::too_many_arguments(checker, function_def);
}
if checker.enabled(Rule::TooManyPositional) {
pylint::rules::too_many_positional(checker, function_def);
if checker.enabled(Rule::TooManyPositionalArguments) {
pylint::rules::too_many_positional_arguments(checker, function_def);
}
if checker.enabled(Rule::TooManyReturnStatements) {
if let Some(diagnostic) = pylint::rules::too_many_return_statements(

View File

@@ -248,7 +248,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Pylint, "R0914") => (RuleGroup::Preview, rules::pylint::rules::TooManyLocals),
(Pylint, "R0915") => (RuleGroup::Stable, rules::pylint::rules::TooManyStatements),
(Pylint, "R0916") => (RuleGroup::Preview, rules::pylint::rules::TooManyBooleanExpressions),
(Pylint, "R0917") => (RuleGroup::Preview, rules::pylint::rules::TooManyPositional),
(Pylint, "R0917") => (RuleGroup::Preview, rules::pylint::rules::TooManyPositionalArguments),
(Pylint, "R1701") => (RuleGroup::Removed, rules::pylint::rules::RepeatedIsinstanceCalls),
(Pylint, "R1702") => (RuleGroup::Preview, rules::pylint::rules::TooManyNestedBlocks),
(Pylint, "R1704") => (RuleGroup::Stable, rules::pylint::rules::RedefinedArgumentFromLocal),

View File

@@ -123,7 +123,10 @@ mod tests {
#[test_case(Rule::RedefinedLoopName, Path::new("redefined_loop_name.py"))]
#[test_case(Rule::ReturnInInit, Path::new("return_in_init.py"))]
#[test_case(Rule::TooManyArguments, Path::new("too_many_arguments.py"))]
#[test_case(Rule::TooManyPositional, Path::new("too_many_positional.py"))]
#[test_case(
Rule::TooManyPositionalArguments,
Path::new("too_many_positional_arguments.py")
)]
#[test_case(Rule::TooManyBranches, Path::new("too_many_branches.py"))]
#[test_case(
Rule::TooManyReturnStatements,
@@ -294,7 +297,7 @@ mod tests {
max_positional_args: 4,
..pylint::settings::Settings::default()
},
..LinterSettings::for_rule(Rule::TooManyPositional)
..LinterSettings::for_rule(Rule::TooManyPositionalArguments)
},
)?;
assert_messages!(diagnostics);

View File

@@ -79,7 +79,7 @@ pub(crate) use too_many_boolean_expressions::*;
pub(crate) use too_many_branches::*;
pub(crate) use too_many_locals::*;
pub(crate) use too_many_nested_blocks::*;
pub(crate) use too_many_positional::*;
pub(crate) use too_many_positional_arguments::*;
pub(crate) use too_many_public_methods::*;
pub(crate) use too_many_return_statements::*;
pub(crate) use too_many_statements::*;
@@ -182,7 +182,7 @@ mod too_many_boolean_expressions;
mod too_many_branches;
mod too_many_locals;
mod too_many_nested_blocks;
mod too_many_positional;
mod too_many_positional_arguments;
mod too_many_public_methods;
mod too_many_return_statements;
mod too_many_statements;

View File

@@ -42,21 +42,24 @@ use crate::checkers::ast::Checker;
/// ## Options
/// - `lint.pylint.max-positional-args`
#[violation]
pub struct TooManyPositional {
pub struct TooManyPositionalArguments {
c_pos: usize,
max_pos: usize,
}
impl Violation for TooManyPositional {
impl Violation for TooManyPositionalArguments {
#[derive_message_formats]
fn message(&self) -> String {
let TooManyPositional { c_pos, max_pos } = self;
let TooManyPositionalArguments { c_pos, max_pos } = self;
format!("Too many positional arguments ({c_pos}/{max_pos})")
}
}
/// PLR0917
pub(crate) fn too_many_positional(checker: &mut Checker, function_def: &ast::StmtFunctionDef) {
pub(crate) fn too_many_positional_arguments(
checker: &mut Checker,
function_def: &ast::StmtFunctionDef,
) {
let semantic = checker.semantic();
// Count the number of positional arguments.
@@ -109,7 +112,7 @@ pub(crate) fn too_many_positional(checker: &mut Checker, function_def: &ast::Stm
}
checker.diagnostics.push(Diagnostic::new(
TooManyPositional {
TooManyPositionalArguments {
c_pos: num_positional_args,
max_pos: checker.settings.pylint.max_positional_args,
},

View File

@@ -1,28 +1,28 @@
---
source: crates/ruff_linter/src/rules/pylint/mod.rs
---
too_many_positional.py:1:5: PLR0917 Too many positional arguments (8/5)
too_many_positional_arguments.py:1:5: PLR0917 Too many positional arguments (8/5)
|
1 | def f(x, y, z, t, u, v, w, r): # Too many positional arguments (8/5)
| ^ PLR0917
2 | pass
|
too_many_positional.py:21:5: PLR0917 Too many positional arguments (6/5)
too_many_positional_arguments.py:21:5: PLR0917 Too many positional arguments (6/5)
|
21 | def f(x, y, z, /, u, v, w): # Too many positional arguments (6/5)
| ^ PLR0917
22 | pass
|
too_many_positional.py:29:5: PLR0917 Too many positional arguments (6/5)
too_many_positional_arguments.py:29:5: PLR0917 Too many positional arguments (6/5)
|
29 | def f(x, y, z, a, b, c, *, u, v, w): # Too many positional arguments (6/5)
| ^ PLR0917
30 | pass
|
too_many_positional.py:43:9: PLR0917 Too many positional arguments (6/5)
too_many_positional_arguments.py:43:9: PLR0917 Too many positional arguments (6/5)
|
41 | pass
42 |
@@ -31,12 +31,10 @@ too_many_positional.py:43:9: PLR0917 Too many positional arguments (6/5)
44 | pass
|
too_many_positional.py:47:9: PLR0917 Too many positional arguments (6/5)
too_many_positional_arguments.py:47:9: PLR0917 Too many positional arguments (6/5)
|
46 | @staticmethod
47 | def f(self, a, b, c, d, e): # Too many positional arguments (6/5)
| ^ PLR0917
48 | pass
|

View File

@@ -84,13 +84,13 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
let (trailing_in_comments, dangling_if_comments) = dangling_comments
.split_at(dangling_comments.partition_point(|comment| comment.start() < iter.start()));
let in_spacer = format_with(|f| {
if before_in_comments.is_empty() {
space().fmt(f)
} else {
soft_line_break_or_space().fmt(f)
}
});
// let in_spacer = format_with(|f| {
// // if before_in_comments.is_empty() {
// // space().fmt(f)
// // } else {
// soft_line_break_or_space().fmt(f)
// // }
// });
write!(
f,
@@ -101,10 +101,12 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
expression: target,
preserve_parentheses: !target.is_tuple_expr()
},
ExprTupleWithoutParentheses(target),
in_spacer,
leading_comments(before_in_comments),
token("in"),
group(&format_args![
ExprTupleWithoutParentheses(target),
soft_line_break_or_space(),
leading_comments(before_in_comments),
token("in"),
]),
trailing_comments(trailing_in_comments),
Spacer {
expression: iter,

View File

@@ -266,7 +266,17 @@ last_call()
```diff
--- Black
+++ Ruff
@@ -115,7 +115,7 @@
@@ -101,7 +101,8 @@
{a: b * -2 for a, b in dictionary.items()}
{
k: v
- for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
+ for k, v
+ in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
}
Python3 > Python2 > COBOL
Life is Life
@@ -115,7 +116,7 @@
arg,
another,
kwarg="hey",
@@ -383,7 +393,8 @@ str or None if (1 if True else 2) else str or bytes or None
{a: b * -2 for a, b in dictionary.items()}
{
k: v
for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
for k, v
in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
}
Python3 > Python2 > COBOL
Life is Life
@@ -1028,5 +1039,3 @@ bbbb >> bbbb * bbbb
last_call()
# standalone comment at ENDMARKER
```

View File

@@ -373,7 +373,7 @@ for foo in ["a", "b"]:
func(
[
@@ -114,13 +140,15 @@
@@ -114,13 +140,16 @@
func(
[x for x in "long line long line long line long line long line long line long line"]
)
@@ -386,7 +386,8 @@ for foo in ["a", "b"]:
- for x in "long line long line long line long line long line long line long line"
+ for x in [
+ x
+ for x in "long line long line long line long line long line long line long line"
+ for x
+ in "long line long line long line long line long line long line long line"
+ ]
]
-])
@@ -394,7 +395,7 @@ for foo in ["a", "b"]:
foooooooooooooooooooo(
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
@@ -131,10 +159,12 @@
@@ -131,10 +160,12 @@
)
nested_mapping = {
@@ -411,7 +412,7 @@ for foo in ["a", "b"]:
}
explicit_exploding = [
[
@@ -144,24 +174,34 @@
@@ -144,24 +175,34 @@
],
],
]
@@ -461,7 +462,7 @@ for foo in ["a", "b"]:
# Edge case when deciding whether to hug the brackets without inner content.
very_very_very_long_variable = very_very_very_long_module.VeryVeryVeryVeryLongClassName(
@@ -169,11 +209,13 @@
@@ -169,11 +210,14 @@
)
for foo in ["a", "b"]:
@@ -478,7 +479,8 @@ for foo in ["a", "b"]:
+ individual
+ for
+ # Foobar
+ container in xs_by_y[foo]
+ container
+ in xs_by_y[foo]
+ # Foobar
+ for individual in container["nested"]
+ ]
@@ -635,7 +637,8 @@ func(
x
for x in [
x
for x in "long line long line long line long line long line long line long line"
for x
in "long line long line long line long line long line long line long line"
]
]
)
@@ -704,7 +707,8 @@ for foo in ["a", "b"]:
individual
for
# Foobar
container in xs_by_y[foo]
container
in xs_by_y[foo]
# Foobar
for individual in container["nested"]
]

View File

@@ -198,7 +198,8 @@ query = {
{
a: a # a
for c in e # for # c # in # e
for c # for # c
in e # in # e
}
{
@@ -232,7 +233,8 @@ query = {
for ccccccccccccccccccccccccccccccccccccccc, ddddddddddddddddddd, [
eeeeeeeeeeeeeeeeeeeeee,
fffffffffffffffffffffffff,
] in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
]
in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
if fffffffffffffffffffffffffffffffffffffffffff
< gggggggggggggggggggggggggggggggggggggggggggggg
< hhhhhhhhhhhhhhhhhhhhhhhhhh
@@ -263,7 +265,8 @@ query = {
a,
a,
a,
] in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
]
in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
}
{
k: v
@@ -288,7 +291,8 @@ query = {
a,
a,
a,
) in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
)
in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
}
# Leading
@@ -315,7 +319,8 @@ query = {
a,
a,
a, # Trailing
) in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension # Trailing
)
in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension # Trailing
} # Trailing
# Trailing
@@ -336,7 +341,8 @@ selected_choices = {
for ( # foo
x,
aaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaayaaaay,
) in z
)
in z
}
a = {
@@ -403,6 +409,3 @@ query = {
for key, queries in self._filters.items()
}
```

View File

@@ -189,7 +189,8 @@ y = [
[
a # a
for c in e # for # c # in # e
for c # for # c
in e # in # e
]
[
@@ -220,7 +221,8 @@ y = [
for ccccccccccccccccccccccccccccccccccccccc, ddddddddddddddddddd, [
eeeeeeeeeeeeeeeeeeeeee,
fffffffffffffffffffffffff,
] in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
]
in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
if fffffffffffffffffffffffffffffffffffffffffff
< gggggggggggggggggggggggggggggggggggggggggggggg
< hhhhhhhhhhhhhhhhhhhhhhhhhh
@@ -304,7 +306,8 @@ aaaaaaaaaaaaaaaaaaaaa = [
for (
x,
y,
) in z
)
in z
if head_name
]
@@ -326,7 +329,8 @@ y = [
(
# comment
a
) in
)
in
(
# comment
x
@@ -350,7 +354,8 @@ y = [
a
for
# comment
a, b in x
a, b
in x
if True
]
@@ -361,7 +366,8 @@ y = [
# comment
a,
b,
) in x
)
in x
if True
]
@@ -370,7 +376,8 @@ y = [
a
for
# comment
a in
a
in
# comment
x
if
@@ -388,7 +395,7 @@ y = [
```diff
--- Stable
+++ Preview
@@ -142,24 +142,20 @@
@@ -145,25 +145,21 @@
# Leading expression comments:
y = [
a
@@ -397,9 +404,10 @@ y = [
+ for (
# comment
a
- ) in
)
- in
- (
+ ) in (
+ in (
# comment
x
)

View File

@@ -74,7 +74,8 @@ selected_choices = {
{
a # a
for c in e # for # c # in # e
for c # for # c
in e # in # e
}
{
@@ -105,7 +106,8 @@ selected_choices = {
for ccccccccccccccccccccccccccccccccccccccc, ddddddddddddddddddd, [
eeeeeeeeeeeeeeeeeeeeee,
fffffffffffffffffffffffff,
] in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
]
in eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffggggggggggggggggggggghhhhhhhhhhhhhhothermoreeand_even_moreddddddddddddddddddddd
if fffffffffffffffffffffffffffffffffffffffffff
< gggggggggggggggggggggggggggggggggggggggggggggg
< hhhhhhhhhhhhhhhhhhhhhhhhhh
@@ -123,6 +125,3 @@ selected_choices = {
if str(v) not in self.choices.field.empty_values
}
```

View File

@@ -1388,10 +1388,10 @@ impl Flake8ImportConventionsOptions {
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Flake8PytestStyleOptions {
/// Boolean flag specifying whether `@pytest.fixture()` without parameters
/// should have parentheses. If the option is set to `true` (the
/// default), `@pytest.fixture()` is valid and `@pytest.fixture` is
/// invalid. If set to `false`, `@pytest.fixture` is valid and
/// `@pytest.fixture()` is invalid.
/// should have parentheses. If the option is set to `false` (the default),
/// `@pytest.fixture` is valid and `@pytest.fixture()` is invalid. If set
/// to `true`, `@pytest.fixture()` is valid and `@pytest.fixture` is
/// invalid.
#[option(
default = "false",
value_type = "bool",
@@ -1471,10 +1471,10 @@ pub struct Flake8PytestStyleOptions {
pub raises_extend_require_match_for: Option<Vec<String>>,
/// Boolean flag specifying whether `@pytest.mark.foo()` without parameters
/// should have parentheses. If the option is set to `true` (the
/// default), `@pytest.mark.foo()` is valid and `@pytest.mark.foo` is
/// invalid. If set to `false`, `@pytest.mark.foo` is valid and
/// `@pytest.mark.foo()` is invalid.
/// should have parentheses. If the option is set to `false` (the
/// default), `@pytest.mark.foo` is valid and `@pytest.mark.foo()` is
/// invalid. If set to `true`, `@pytest.mark.foo()` is valid and
/// `@pytest.mark.foo` is invalid.
#[option(
default = "false",
value_type = "bool",

4
ruff.schema.json generated
View File

@@ -1103,14 +1103,14 @@
"type": "object",
"properties": {
"fixture-parentheses": {
"description": "Boolean flag specifying whether `@pytest.fixture()` without parameters should have parentheses. If the option is set to `true` (the default), `@pytest.fixture()` is valid and `@pytest.fixture` is invalid. If set to `false`, `@pytest.fixture` is valid and `@pytest.fixture()` is invalid.",
"description": "Boolean flag specifying whether `@pytest.fixture()` without parameters should have parentheses. If the option is set to `false` (the default), `@pytest.fixture` is valid and `@pytest.fixture()` is invalid. If set to `true`, `@pytest.fixture()` is valid and `@pytest.fixture` is invalid.",
"type": [
"boolean",
"null"
]
},
"mark-parentheses": {
"description": "Boolean flag specifying whether `@pytest.mark.foo()` without parameters should have parentheses. If the option is set to `true` (the default), `@pytest.mark.foo()` is valid and `@pytest.mark.foo` is invalid. If set to `false`, `@pytest.mark.foo` is valid and `@pytest.mark.foo()` is invalid.",
"description": "Boolean flag specifying whether `@pytest.mark.foo()` without parameters should have parentheses. If the option is set to `false` (the default), `@pytest.mark.foo` is valid and `@pytest.mark.foo()` is invalid. If set to `true`, `@pytest.mark.foo()` is valid and `@pytest.mark.foo` is invalid.",
"type": [
"boolean",
"null"