mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-01 12:25:45 +00:00
[flake8-bugbear] Include certain guaranteed-mutable expressions: tuples, generators, and assignment expressions (B006) (#20024)
Some checks are pending
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary Resolves #20004 The implementation now supports guaranteed-mutable expressions in the following cases: - Tuple literals with mutable elements (supporting deep nesting) - Generator expressions - Named expressions (walrus operator) containing mutable components Preserves original formatting for assignment value: ```python # Test case def f5(x=([1, ])): print(x) ``` ```python # Fix before def f5(x=(None)): if x is None: x = [1] print(x) ``` ```python # Fix after def f5(x=None): if x is None: x = ([1, ]) print(x) ``` The expansion of detected expressions and the new fixes gated behind previews. ## Test Plan - Added B006_9.py with a bunch of test cases - Generated snapshots --------- Co-authored-by: Igor Drokin <drokinii1017@gmail.com> Co-authored-by: dylwil3 <dylwil3@gmail.com>
This commit is contained in:
parent
805d179dc0
commit
673167a565
16 changed files with 1249 additions and 32 deletions
26
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B006_9.py
vendored
Normal file
26
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B006_9.py
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
def f1(x=([],)):
|
||||
print(x)
|
||||
|
||||
|
||||
def f2(x=(x for x in "x")):
|
||||
print(x)
|
||||
|
||||
|
||||
def f3(x=((x for x in "x"),)):
|
||||
print(x)
|
||||
|
||||
|
||||
def f4(x=(z := [1, ])):
|
||||
print(x)
|
||||
|
||||
|
||||
def f5(x=([1, ])):
|
||||
print(x)
|
||||
|
||||
|
||||
def w1(x=(1,)):
|
||||
print(x)
|
||||
|
||||
|
||||
def w2(x=(z := 3)):
|
||||
print(x)
|
||||
|
|
@ -245,3 +245,17 @@ pub(crate) const fn is_a003_class_scope_shadowing_expansion_enabled(
|
|||
pub(crate) const fn is_refined_submodule_import_match_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// github.com/astral-sh/ruff/issues/20004
|
||||
pub(crate) const fn is_b006_check_guaranteed_mutable_expr_enabled(
|
||||
settings: &LinterSettings,
|
||||
) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// github.com/astral-sh/ruff/issues/20004
|
||||
pub(crate) const fn is_b006_unsafe_fix_preserve_assignment_expr_enabled(
|
||||
settings: &LinterSettings,
|
||||
) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ mod tests {
|
|||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_6.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_7.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_8.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_9.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_B008.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_1.pyi"))]
|
||||
#[test_case(Rule::NoExplicitStacklevel, Path::new("B028.py"))]
|
||||
|
|
@ -83,6 +84,17 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test_case(Rule::MapWithoutExplicitStrict, Path::new("B912.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_1.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_2.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_3.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_4.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_5.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_6.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_7.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_8.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_9.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_B008.py"))]
|
||||
#[test_case(Rule::MutableArgumentDefault, Path::new("B006_1.pyi"))]
|
||||
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview__{}_{}",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use std::fmt::Write;
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::is_docstring_stmt;
|
||||
use ruff_python_ast::name::QualifiedName;
|
||||
use ruff_python_ast::{self as ast, Expr, Parameter};
|
||||
use ruff_python_codegen::{Generator, Stylist};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr, ParameterWithDefault};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_semantic::analyze::function_type::is_stub;
|
||||
use ruff_python_semantic::analyze::typing::{is_immutable_annotation, is_mutable_expr};
|
||||
|
|
@ -13,8 +12,11 @@ use ruff_python_trivia::{indentation_at_offset, textwrap};
|
|||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::Locator;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::preview::{
|
||||
is_b006_check_guaranteed_mutable_expr_enabled,
|
||||
is_b006_unsafe_fix_preserve_assignment_expr_enabled,
|
||||
};
|
||||
use crate::{Edit, Fix, FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
|
|
@ -111,8 +113,12 @@ pub(crate) fn mutable_argument_default(checker: &Checker, function_def: &ast::St
|
|||
.iter()
|
||||
.map(|target| QualifiedName::from_dotted_name(target))
|
||||
.collect();
|
||||
|
||||
if is_mutable_expr(default, checker.semantic())
|
||||
let is_mut_expr = if is_b006_check_guaranteed_mutable_expr_enabled(checker.settings()) {
|
||||
is_guaranteed_mutable_expr(default, checker.semantic())
|
||||
} else {
|
||||
is_mutable_expr(default, checker.semantic())
|
||||
};
|
||||
if is_mut_expr
|
||||
&& !parameter.annotation().is_some_and(|expr| {
|
||||
is_immutable_annotation(expr, checker.semantic(), extend_immutable_calls.as_slice())
|
||||
})
|
||||
|
|
@ -120,35 +126,37 @@ pub(crate) fn mutable_argument_default(checker: &Checker, function_def: &ast::St
|
|||
let mut diagnostic = checker.report_diagnostic(MutableArgumentDefault, default.range());
|
||||
|
||||
// If the function body is on the same line as the function def, do not fix
|
||||
if let Some(fix) = move_initialization(
|
||||
function_def,
|
||||
¶meter.parameter,
|
||||
default,
|
||||
checker.semantic(),
|
||||
checker.locator(),
|
||||
checker.stylist(),
|
||||
checker.indexer(),
|
||||
checker.generator(),
|
||||
) {
|
||||
if let Some(fix) = move_initialization(function_def, parameter, default, checker) {
|
||||
diagnostic.set_fix(fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the expression is guaranteed to create a mutable object.
|
||||
fn is_guaranteed_mutable_expr(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
match expr {
|
||||
Expr::Generator(_) => true,
|
||||
Expr::Tuple(ast::ExprTuple { elts, .. }) => {
|
||||
elts.iter().any(|e| is_guaranteed_mutable_expr(e, semantic))
|
||||
}
|
||||
Expr::Named(ast::ExprNamed { value, .. }) => is_guaranteed_mutable_expr(value, semantic),
|
||||
_ => is_mutable_expr(expr, semantic),
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a [`Fix`] to move a mutable argument default initialization
|
||||
/// into the function body.
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
fn move_initialization(
|
||||
function_def: &ast::StmtFunctionDef,
|
||||
parameter: &Parameter,
|
||||
parameter: &ParameterWithDefault,
|
||||
default: &Expr,
|
||||
semantic: &SemanticModel,
|
||||
locator: &Locator,
|
||||
stylist: &Stylist,
|
||||
indexer: &Indexer,
|
||||
generator: Generator,
|
||||
checker: &Checker,
|
||||
) -> Option<Fix> {
|
||||
let indexer = checker.indexer();
|
||||
let locator = checker.locator();
|
||||
let stylist = checker.stylist();
|
||||
|
||||
let mut body = function_def.body.iter().peekable();
|
||||
|
||||
// Avoid attempting to fix single-line functions.
|
||||
|
|
@ -157,25 +165,58 @@ fn move_initialization(
|
|||
return None;
|
||||
}
|
||||
|
||||
let range = match parenthesized_range(
|
||||
default.into(),
|
||||
parameter.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
) {
|
||||
Some(range) => range,
|
||||
None => default.range(),
|
||||
};
|
||||
// Set the default argument value to `None`.
|
||||
let default_edit = Edit::range_replacement("None".to_string(), default.range());
|
||||
let default_edit = Edit::range_replacement("None".to_string(), range);
|
||||
|
||||
// If the function is a stub, this is the only necessary edit.
|
||||
if is_stub(function_def, semantic) {
|
||||
if is_stub(function_def, checker.semantic()) {
|
||||
return Some(Fix::unsafe_edit(default_edit));
|
||||
}
|
||||
|
||||
// Add an `if`, to set the argument to its original value if still `None`.
|
||||
let mut content = String::new();
|
||||
let _ = write!(&mut content, "if {} is None:", parameter.name());
|
||||
let _ = write!(&mut content, "if {} is None:", parameter.parameter.name());
|
||||
content.push_str(stylist.line_ending().as_str());
|
||||
content.push_str(stylist.indentation());
|
||||
let _ = write!(
|
||||
&mut content,
|
||||
"{} = {}",
|
||||
parameter.name(),
|
||||
generator.expr(default)
|
||||
);
|
||||
if is_b006_unsafe_fix_preserve_assignment_expr_enabled(checker.settings()) {
|
||||
let annotation = if let Some(ann) = parameter.annotation() {
|
||||
format!(": {}", locator.slice(ann))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let _ = write!(
|
||||
&mut content,
|
||||
"{}{} = {}",
|
||||
parameter.parameter.name(),
|
||||
annotation,
|
||||
locator.slice(
|
||||
parenthesized_range(
|
||||
default.into(),
|
||||
parameter.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source()
|
||||
)
|
||||
.unwrap_or(default.range())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
let _ = write!(
|
||||
&mut content,
|
||||
"{} = {}",
|
||||
parameter.name(),
|
||||
checker.generator().expr(default)
|
||||
);
|
||||
}
|
||||
|
||||
content.push_str(stylist.line_ending().as_str());
|
||||
|
||||
// Determine the indentation depth of the function body.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:17:11
|
||||
|
|
||||
17 | def f5(x=([1, ])):
|
||||
| ^^^^^
|
||||
18 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
14 | print(x)
|
||||
15 |
|
||||
16 |
|
||||
- def f5(x=([1, ])):
|
||||
17 + def f5(x=None):
|
||||
18 + if x is None:
|
||||
19 + x = [1]
|
||||
20 | print(x)
|
||||
21 |
|
||||
22 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_1.py:3:22
|
||||
|
|
||||
1 | # Docstring followed by a newline
|
||||
2 |
|
||||
3 | def foobar(foor, bar={}):
|
||||
| ^^
|
||||
4 | """
|
||||
5 | """
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
1 | # Docstring followed by a newline
|
||||
2 |
|
||||
- def foobar(foor, bar={}):
|
||||
3 + def foobar(foor, bar=None):
|
||||
4 | """
|
||||
5 | """
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_2.py:4:22
|
||||
|
|
||||
2 | # Regression test for https://github.com/astral-sh/ruff/issues/7155
|
||||
3 |
|
||||
4 | def foobar(foor, bar={}):
|
||||
| ^^
|
||||
5 | """
|
||||
6 | """
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
1 | # Docstring followed by whitespace with no newline
|
||||
2 | # Regression test for https://github.com/astral-sh/ruff/issues/7155
|
||||
3 |
|
||||
- def foobar(foor, bar={}):
|
||||
4 + def foobar(foor, bar=None):
|
||||
5 | """
|
||||
6 | """
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_3.py:4:22
|
||||
|
|
||||
4 | def foobar(foor, bar={}):
|
||||
| ^^
|
||||
5 | """
|
||||
6 | """
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
1 | # Docstring with no newline
|
||||
2 |
|
||||
3 |
|
||||
- def foobar(foor, bar={}):
|
||||
4 + def foobar(foor, bar=None):
|
||||
5 | """
|
||||
6 | """
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_4.py:7:26
|
||||
|
|
||||
6 | class FormFeedIndent:
|
||||
7 | def __init__(self, a=[]):
|
||||
| ^^
|
||||
8 | print(a)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
4 |
|
||||
5 |
|
||||
6 | class FormFeedIndent:
|
||||
- def __init__(self, a=[]):
|
||||
7 + def __init__(self, a=None):
|
||||
8 + if a is None:
|
||||
9 + a = []
|
||||
10 | print(a)
|
||||
11 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:5:49
|
||||
|
|
||||
5 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
6 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
2 | # https://github.com/astral-sh/ruff/issues/7616
|
||||
3 |
|
||||
4 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
5 + def import_module_wrong(value: dict[str, str] = None):
|
||||
6 | import os
|
||||
7 + if value is None:
|
||||
8 + value: dict[str, str] = {}
|
||||
9 |
|
||||
10 |
|
||||
11 | def import_module_with_values_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:9:61
|
||||
|
|
||||
9 | def import_module_with_values_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
10 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
6 | import os
|
||||
7 |
|
||||
8 |
|
||||
- def import_module_with_values_wrong(value: dict[str, str] = {}):
|
||||
9 + def import_module_with_values_wrong(value: dict[str, str] = None):
|
||||
10 | import os
|
||||
11 |
|
||||
12 + if value is None:
|
||||
13 + value: dict[str, str] = {}
|
||||
14 | return 2
|
||||
15 |
|
||||
16 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:15:50
|
||||
|
|
||||
15 | def import_modules_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
16 | import os
|
||||
17 | import sys
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
12 | return 2
|
||||
13 |
|
||||
14 |
|
||||
- def import_modules_wrong(value: dict[str, str] = {}):
|
||||
15 + def import_modules_wrong(value: dict[str, str] = None):
|
||||
16 | import os
|
||||
17 | import sys
|
||||
18 | import itertools
|
||||
19 + if value is None:
|
||||
20 + value: dict[str, str] = {}
|
||||
21 |
|
||||
22 |
|
||||
23 | def from_import_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:21:54
|
||||
|
|
||||
21 | def from_import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
22 | from os import path
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
18 | import itertools
|
||||
19 |
|
||||
20 |
|
||||
- def from_import_module_wrong(value: dict[str, str] = {}):
|
||||
21 + def from_import_module_wrong(value: dict[str, str] = None):
|
||||
22 | from os import path
|
||||
23 + if value is None:
|
||||
24 + value: dict[str, str] = {}
|
||||
25 |
|
||||
26 |
|
||||
27 | def from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:25:55
|
||||
|
|
||||
25 | def from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
26 | from os import path
|
||||
27 | from sys import version_info
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
22 | from os import path
|
||||
23 |
|
||||
24 |
|
||||
- def from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
25 + def from_imports_module_wrong(value: dict[str, str] = None):
|
||||
26 | from os import path
|
||||
27 | from sys import version_info
|
||||
28 + if value is None:
|
||||
29 + value: dict[str, str] = {}
|
||||
30 |
|
||||
31 |
|
||||
32 | def import_and_from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:30:66
|
||||
|
|
||||
30 | def import_and_from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
31 | import os
|
||||
32 | from sys import version_info
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
27 | from sys import version_info
|
||||
28 |
|
||||
29 |
|
||||
- def import_and_from_imports_module_wrong(value: dict[str, str] = {}):
|
||||
30 + def import_and_from_imports_module_wrong(value: dict[str, str] = None):
|
||||
31 | import os
|
||||
32 | from sys import version_info
|
||||
33 + if value is None:
|
||||
34 + value: dict[str, str] = {}
|
||||
35 |
|
||||
36 |
|
||||
37 | def import_docstring_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:35:59
|
||||
|
|
||||
35 | def import_docstring_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
36 | """Docstring"""
|
||||
37 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
32 | from sys import version_info
|
||||
33 |
|
||||
34 |
|
||||
- def import_docstring_module_wrong(value: dict[str, str] = {}):
|
||||
35 + def import_docstring_module_wrong(value: dict[str, str] = None):
|
||||
36 | """Docstring"""
|
||||
37 | import os
|
||||
38 + if value is None:
|
||||
39 + value: dict[str, str] = {}
|
||||
40 |
|
||||
41 |
|
||||
42 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:40:49
|
||||
|
|
||||
40 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
41 | """Docstring"""
|
||||
42 | import os; import sys
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
37 | import os
|
||||
38 |
|
||||
39 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
40 + def import_module_wrong(value: dict[str, str] = None):
|
||||
41 | """Docstring"""
|
||||
42 | import os; import sys
|
||||
43 + if value is None:
|
||||
44 + value: dict[str, str] = {}
|
||||
45 |
|
||||
46 |
|
||||
47 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:45:49
|
||||
|
|
||||
45 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
46 | """Docstring"""
|
||||
47 | import os; import sys; x = 1
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
42 | import os; import sys
|
||||
43 |
|
||||
44 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
45 + def import_module_wrong(value: dict[str, str] = None):
|
||||
46 | """Docstring"""
|
||||
47 + if value is None:
|
||||
48 + value: dict[str, str] = {}
|
||||
49 | import os; import sys; x = 1
|
||||
50 |
|
||||
51 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:50:49
|
||||
|
|
||||
50 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
51 | """Docstring"""
|
||||
52 | import os; import sys
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
47 | import os; import sys; x = 1
|
||||
48 |
|
||||
49 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
50 + def import_module_wrong(value: dict[str, str] = None):
|
||||
51 | """Docstring"""
|
||||
52 | import os; import sys
|
||||
53 + if value is None:
|
||||
54 + value: dict[str, str] = {}
|
||||
55 |
|
||||
56 |
|
||||
57 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:55:49
|
||||
|
|
||||
55 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
56 | import os; import sys
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
52 | import os; import sys
|
||||
53 |
|
||||
54 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
55 + def import_module_wrong(value: dict[str, str] = None):
|
||||
56 | import os; import sys
|
||||
57 + if value is None:
|
||||
58 + value: dict[str, str] = {}
|
||||
59 |
|
||||
60 |
|
||||
61 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:59:49
|
||||
|
|
||||
59 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
60 | import os; import sys; x = 1
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
56 | import os; import sys
|
||||
57 |
|
||||
58 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
59 + def import_module_wrong(value: dict[str, str] = None):
|
||||
60 + if value is None:
|
||||
61 + value: dict[str, str] = {}
|
||||
62 | import os; import sys; x = 1
|
||||
63 |
|
||||
64 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:63:49
|
||||
|
|
||||
63 | def import_module_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
64 | import os; import sys
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
60 | import os; import sys; x = 1
|
||||
61 |
|
||||
62 |
|
||||
- def import_module_wrong(value: dict[str, str] = {}):
|
||||
63 + def import_module_wrong(value: dict[str, str] = None):
|
||||
64 | import os; import sys
|
||||
65 + if value is None:
|
||||
66 + value: dict[str, str] = {}
|
||||
67 |
|
||||
68 |
|
||||
69 | def import_module_wrong(value: dict[str, str] = {}): import os
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:67:49
|
||||
|
|
||||
67 | def import_module_wrong(value: dict[str, str] = {}): import os
|
||||
| ^^
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
|
||||
B006 Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:70:49
|
||||
|
|
||||
70 | def import_module_wrong(value: dict[str, str] = {}): import os; import sys
|
||||
| ^^
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
|
||||
B006 Do not use mutable data structures for argument defaults
|
||||
--> B006_5.py:73:49
|
||||
|
|
||||
73 | def import_module_wrong(value: dict[str, str] = {}): \
|
||||
| ^^
|
||||
74 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_6.py:4:22
|
||||
|
|
||||
2 | # Same as B006_2.py, but import instead of docstring
|
||||
3 |
|
||||
4 | def foobar(foor, bar={}):
|
||||
| ^^
|
||||
5 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
1 | # Import followed by whitespace with no newline
|
||||
2 | # Same as B006_2.py, but import instead of docstring
|
||||
3 |
|
||||
- def foobar(foor, bar={}):
|
||||
- import os
|
||||
4 + def foobar(foor, bar=None):
|
||||
5 + import os
|
||||
6 + if bar is None:
|
||||
7 + bar = {}
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_7.py:4:22
|
||||
|
|
||||
2 | # Same as B006_3.py, but import instead of docstring
|
||||
3 |
|
||||
4 | def foobar(foor, bar={}):
|
||||
| ^^
|
||||
5 | import os
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
1 | # Import with no newline
|
||||
2 | # Same as B006_3.py, but import instead of docstring
|
||||
3 |
|
||||
- def foobar(foor, bar={}):
|
||||
- import os
|
||||
4 + def foobar(foor, bar=None):
|
||||
5 + import os
|
||||
6 + if bar is None:
|
||||
7 + bar = {}
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_8.py:1:19
|
||||
|
|
||||
1 | def foo(a: list = []):
|
||||
| ^^
|
||||
2 | raise NotImplementedError("")
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
- def foo(a: list = []):
|
||||
1 + def foo(a: list = None):
|
||||
2 | raise NotImplementedError("")
|
||||
3 |
|
||||
4 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_8.py:5:19
|
||||
|
|
||||
5 | def bar(a: dict = {}):
|
||||
| ^^
|
||||
6 | """ This one also has a docstring"""
|
||||
7 | raise NotImplementedError("and has some text in here")
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
2 | raise NotImplementedError("")
|
||||
3 |
|
||||
4 |
|
||||
- def bar(a: dict = {}):
|
||||
5 + def bar(a: dict = None):
|
||||
6 | """ This one also has a docstring"""
|
||||
7 | raise NotImplementedError("and has some text in here")
|
||||
8 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_8.py:10:19
|
||||
|
|
||||
10 | def baz(a: list = []):
|
||||
| ^^
|
||||
11 | """This one raises a different exception"""
|
||||
12 | raise IndexError()
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
7 | raise NotImplementedError("and has some text in here")
|
||||
8 |
|
||||
9 |
|
||||
- def baz(a: list = []):
|
||||
10 + def baz(a: list = None):
|
||||
11 | """This one raises a different exception"""
|
||||
12 + if a is None:
|
||||
13 + a: list = []
|
||||
14 | raise IndexError()
|
||||
15 |
|
||||
16 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_8.py:15:19
|
||||
|
|
||||
15 | def qux(a: list = []):
|
||||
| ^^
|
||||
16 | raise NotImplementedError
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
12 | raise IndexError()
|
||||
13 |
|
||||
14 |
|
||||
- def qux(a: list = []):
|
||||
15 + def qux(a: list = None):
|
||||
16 | raise NotImplementedError
|
||||
17 |
|
||||
18 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_8.py:19:20
|
||||
|
|
||||
19 | def quux(a: list = []):
|
||||
| ^^
|
||||
20 | raise NotImplemented
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
16 | raise NotImplementedError
|
||||
17 |
|
||||
18 |
|
||||
- def quux(a: list = []):
|
||||
19 + def quux(a: list = None):
|
||||
20 | raise NotImplemented
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:1:10
|
||||
|
|
||||
1 | def f1(x=([],)):
|
||||
| ^^^^^
|
||||
2 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
- def f1(x=([],)):
|
||||
1 + def f1(x=None):
|
||||
2 + if x is None:
|
||||
3 + x = ([],)
|
||||
4 | print(x)
|
||||
5 |
|
||||
6 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:5:10
|
||||
|
|
||||
5 | def f2(x=(x for x in "x")):
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
6 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
2 | print(x)
|
||||
3 |
|
||||
4 |
|
||||
- def f2(x=(x for x in "x")):
|
||||
5 + def f2(x=None):
|
||||
6 + if x is None:
|
||||
7 + x = (x for x in "x")
|
||||
8 | print(x)
|
||||
9 |
|
||||
10 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:9:10
|
||||
|
|
||||
9 | def f3(x=((x for x in "x"),)):
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
10 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
6 | print(x)
|
||||
7 |
|
||||
8 |
|
||||
- def f3(x=((x for x in "x"),)):
|
||||
9 + def f3(x=None):
|
||||
10 + if x is None:
|
||||
11 + x = ((x for x in "x"),)
|
||||
12 | print(x)
|
||||
13 |
|
||||
14 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:13:11
|
||||
|
|
||||
13 | def f4(x=(z := [1, ])):
|
||||
| ^^^^^^^^^^
|
||||
14 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
10 | print(x)
|
||||
11 |
|
||||
12 |
|
||||
- def f4(x=(z := [1, ])):
|
||||
13 + def f4(x=None):
|
||||
14 + if x is None:
|
||||
15 + x = (z := [1, ])
|
||||
16 | print(x)
|
||||
17 |
|
||||
18 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_9.py:17:11
|
||||
|
|
||||
17 | def f5(x=([1, ])):
|
||||
| ^^^^^
|
||||
18 | print(x)
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
14 | print(x)
|
||||
15 |
|
||||
16 |
|
||||
- def f5(x=([1, ])):
|
||||
17 + def f5(x=None):
|
||||
18 + if x is None:
|
||||
19 + x = ([1, ])
|
||||
20 | print(x)
|
||||
21 |
|
||||
22 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
|
@ -0,0 +1,462 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:63:25
|
||||
|
|
||||
63 | def this_is_wrong(value=[1, 2, 3]):
|
||||
| ^^^^^^^^^
|
||||
64 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
60 | # Flag mutable literals/comprehensions
|
||||
61 |
|
||||
62 |
|
||||
- def this_is_wrong(value=[1, 2, 3]):
|
||||
63 + def this_is_wrong(value=None):
|
||||
64 | ...
|
||||
65 |
|
||||
66 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:67:30
|
||||
|
|
||||
67 | def this_is_also_wrong(value={}):
|
||||
| ^^
|
||||
68 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
64 | ...
|
||||
65 |
|
||||
66 |
|
||||
- def this_is_also_wrong(value={}):
|
||||
67 + def this_is_also_wrong(value=None):
|
||||
68 | ...
|
||||
69 |
|
||||
70 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:73:52
|
||||
|
|
||||
71 | class Foo:
|
||||
72 | @staticmethod
|
||||
73 | def this_is_also_wrong_and_more_indented(value={}):
|
||||
| ^^
|
||||
74 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
70 |
|
||||
71 | class Foo:
|
||||
72 | @staticmethod
|
||||
- def this_is_also_wrong_and_more_indented(value={}):
|
||||
73 + def this_is_also_wrong_and_more_indented(value=None):
|
||||
74 | pass
|
||||
75 |
|
||||
76 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:77:31
|
||||
|
|
||||
77 | def multiline_arg_wrong(value={
|
||||
| _______________________________^
|
||||
78 | |
|
||||
79 | | }):
|
||||
| |_^
|
||||
80 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
74 | pass
|
||||
75 |
|
||||
76 |
|
||||
- def multiline_arg_wrong(value={
|
||||
-
|
||||
- }):
|
||||
77 + def multiline_arg_wrong(value=None):
|
||||
78 | ...
|
||||
79 |
|
||||
80 | def single_line_func_wrong(value = {}): ...
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:82:36
|
||||
|
|
||||
80 | ...
|
||||
81 |
|
||||
82 | def single_line_func_wrong(value = {}): ...
|
||||
| ^^
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:85:20
|
||||
|
|
||||
85 | def and_this(value=set()):
|
||||
| ^^^^^
|
||||
86 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
82 | def single_line_func_wrong(value = {}): ...
|
||||
83 |
|
||||
84 |
|
||||
- def and_this(value=set()):
|
||||
85 + def and_this(value=None):
|
||||
86 | ...
|
||||
87 |
|
||||
88 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:89:20
|
||||
|
|
||||
89 | def this_too(value=collections.OrderedDict()):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
90 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
86 | ...
|
||||
87 |
|
||||
88 |
|
||||
- def this_too(value=collections.OrderedDict()):
|
||||
89 + def this_too(value=None):
|
||||
90 | ...
|
||||
91 |
|
||||
92 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:93:32
|
||||
|
|
||||
93 | async def async_this_too(value=collections.defaultdict()):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
94 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
90 | ...
|
||||
91 |
|
||||
92 |
|
||||
- async def async_this_too(value=collections.defaultdict()):
|
||||
93 + async def async_this_too(value=None):
|
||||
94 | ...
|
||||
95 |
|
||||
96 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:97:26
|
||||
|
|
||||
97 | def dont_forget_me(value=collections.deque()):
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
98 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
94 | ...
|
||||
95 |
|
||||
96 |
|
||||
- def dont_forget_me(value=collections.deque()):
|
||||
97 + def dont_forget_me(value=None):
|
||||
98 | ...
|
||||
99 |
|
||||
100 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:102:46
|
||||
|
|
||||
101 | # N.B. we're also flagging the function call in the comprehension
|
||||
102 | def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
103 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
99 |
|
||||
100 |
|
||||
101 | # N.B. we're also flagging the function call in the comprehension
|
||||
- def list_comprehension_also_not_okay(default=[i**2 for i in range(3)]):
|
||||
102 + def list_comprehension_also_not_okay(default=None):
|
||||
103 | pass
|
||||
104 |
|
||||
105 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:106:46
|
||||
|
|
||||
106 | def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
107 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
103 | pass
|
||||
104 |
|
||||
105 |
|
||||
- def dict_comprehension_also_not_okay(default={i: i**2 for i in range(3)}):
|
||||
106 + def dict_comprehension_also_not_okay(default=None):
|
||||
107 | pass
|
||||
108 |
|
||||
109 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:110:45
|
||||
|
|
||||
110 | def set_comprehension_also_not_okay(default={i**2 for i in range(3)}):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
111 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
107 | pass
|
||||
108 |
|
||||
109 |
|
||||
- def set_comprehension_also_not_okay(default={i**2 for i in range(3)}):
|
||||
110 + def set_comprehension_also_not_okay(default=None):
|
||||
111 | pass
|
||||
112 |
|
||||
113 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:114:33
|
||||
|
|
||||
114 | def kwonlyargs_mutable(*, value=[]):
|
||||
| ^^
|
||||
115 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
111 | pass
|
||||
112 |
|
||||
113 |
|
||||
- def kwonlyargs_mutable(*, value=[]):
|
||||
114 + def kwonlyargs_mutable(*, value=None):
|
||||
115 | ...
|
||||
116 |
|
||||
117 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:239:20
|
||||
|
|
||||
237 | # B006 and B008
|
||||
238 | # We should handle arbitrary nesting of these B008.
|
||||
239 | def nested_combo(a=[float(3), dt.datetime.now()]):
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
240 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
236 |
|
||||
237 | # B006 and B008
|
||||
238 | # We should handle arbitrary nesting of these B008.
|
||||
- def nested_combo(a=[float(3), dt.datetime.now()]):
|
||||
239 + def nested_combo(a=None):
|
||||
240 | pass
|
||||
241 |
|
||||
242 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:276:27
|
||||
|
|
||||
275 | def mutable_annotations(
|
||||
276 | a: list[int] | None = [],
|
||||
| ^^
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
273 |
|
||||
274 |
|
||||
275 | def mutable_annotations(
|
||||
- a: list[int] | None = [],
|
||||
276 + a: list[int] | None = None,
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:277:35
|
||||
|
|
||||
275 | def mutable_annotations(
|
||||
276 | a: list[int] | None = [],
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
| ^^
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
274 |
|
||||
275 | def mutable_annotations(
|
||||
276 | a: list[int] | None = [],
|
||||
- b: Optional[Dict[int, int]] = {},
|
||||
277 + b: Optional[Dict[int, int]] = None,
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
280 | ):
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:278:62
|
||||
|
|
||||
276 | a: list[int] | None = [],
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
| ^^^^^
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
280 | ):
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
275 | def mutable_annotations(
|
||||
276 | a: list[int] | None = [],
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
- c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
278 + c: Annotated[Union[Set[str], abc.Sized], "annotation"] = None,
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
280 | ):
|
||||
281 | pass
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:279:80
|
||||
|
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
279 | d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
| ^^^^^
|
||||
280 | ):
|
||||
281 | pass
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
276 | a: list[int] | None = [],
|
||||
277 | b: Optional[Dict[int, int]] = {},
|
||||
278 | c: Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
- d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = set(),
|
||||
279 + d: typing_extensions.Annotated[Union[Set[str], abc.Sized], "annotation"] = None,
|
||||
280 | ):
|
||||
281 | pass
|
||||
282 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:284:52
|
||||
|
|
||||
284 | def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
285 | """Docstring"""
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
281 | pass
|
||||
282 |
|
||||
283 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
284 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
285 | """Docstring"""
|
||||
286 |
|
||||
287 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:288:52
|
||||
|
|
||||
288 | def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
289 | """Docstring"""
|
||||
290 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
285 | """Docstring"""
|
||||
286 |
|
||||
287 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
288 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
289 | """Docstring"""
|
||||
290 | ...
|
||||
291 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:293:52
|
||||
|
|
||||
293 | def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
294 | """Docstring"""; ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
290 | ...
|
||||
291 |
|
||||
292 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
293 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
294 | """Docstring"""; ...
|
||||
295 |
|
||||
296 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:297:52
|
||||
|
|
||||
297 | def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
298 | """Docstring"""; \
|
||||
299 | ...
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
294 | """Docstring"""; ...
|
||||
295 |
|
||||
296 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
297 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
298 | """Docstring"""; \
|
||||
299 | ...
|
||||
300 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:302:52
|
||||
|
|
||||
302 | def single_line_func_wrong(value: dict[str, str] = {
|
||||
| ____________________________________________________^
|
||||
303 | | # This is a comment
|
||||
304 | | }):
|
||||
| |_^
|
||||
305 | """Docstring"""
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
299 | ...
|
||||
300 |
|
||||
301 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {
|
||||
- # This is a comment
|
||||
- }):
|
||||
302 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
303 | """Docstring"""
|
||||
304 |
|
||||
305 |
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
B006 Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:308:52
|
||||
|
|
||||
308 | def single_line_func_wrong(value: dict[str, str] = {}) \
|
||||
| ^^
|
||||
309 | : \
|
||||
310 | """Docstring"""
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
|
||||
B006 [*] Do not use mutable data structures for argument defaults
|
||||
--> B006_B008.py:313:52
|
||||
|
|
||||
313 | def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
| ^^
|
||||
314 | """Docstring without newline"""
|
||||
|
|
||||
help: Replace with `None`; initialize within function
|
||||
310 | """Docstring"""
|
||||
311 |
|
||||
312 |
|
||||
- def single_line_func_wrong(value: dict[str, str] = {}):
|
||||
313 + def single_line_func_wrong(value: dict[str, str] = None):
|
||||
314 | """Docstring without newline"""
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
Loading…
Add table
Add a link
Reference in a new issue