Compare commits

...

8 Commits

Author SHA1 Message Date
Charlie Marsh
e9a236f740 Bump version to 0.0.209 2023-01-03 08:27:28 -05:00
Ran Benita
ebb31dc29b Fix PT006 autofix of parametrize name strings like ' first, , second ' (#1591) 2023-01-03 08:12:09 -05:00
Charlie Marsh
b9e92affb1 Avoid silently dropping code generator errors (#1598) 2023-01-03 08:11:18 -05:00
Charlie Marsh
68fbd0f029 Preserve style when generating flake8-simplify messages (#1599) 2023-01-03 08:05:55 -05:00
Charlie Marsh
8d01efb571 Avoid hard unwrap in PT checks (#1597) 2023-01-03 07:39:52 -05:00
Pedram Navid
da5a25b421 Add autofix for SIM300 (#1588) 2023-01-03 07:19:04 -05:00
Charlie Marsh
bfdab4ac94 Add flake8-pytest-style settings to hash (#1595) 2023-01-03 07:12:33 -05:00
jvstme
d1389894a4 Fix several typos in README (#1590) 2023-01-03 07:06:43 -05:00
29 changed files with 320 additions and 162 deletions

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.208
rev: v0.0.209
hooks:
- id: ruff

8
Cargo.lock generated
View File

@@ -744,7 +744,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.208-dev.0"
version = "0.0.209-dev.0"
dependencies = [
"anyhow",
"clap 4.0.32",
@@ -1873,7 +1873,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.208"
version = "0.0.209"
dependencies = [
"annotate-snippets 0.9.1",
"anyhow",
@@ -1941,7 +1941,7 @@ dependencies = [
[[package]]
name = "ruff_dev"
version = "0.0.208"
version = "0.0.209"
dependencies = [
"anyhow",
"clap 4.0.32",
@@ -1962,7 +1962,7 @@ dependencies = [
[[package]]
name = "ruff_macros"
version = "0.0.208"
version = "0.0.209"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -6,7 +6,7 @@ members = [
[package]
name = "ruff"
version = "0.0.208"
version = "0.0.209"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
edition = "2021"
rust-version = "1.65.0"
@@ -51,7 +51,7 @@ path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix
quick-junit = { version = "0.3.2" }
regex = { version = "1.6.0" }
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
ruff_macros = { version = "0.0.208", path = "ruff_macros" }
ruff_macros = { version = "0.0.209", path = "ruff_macros" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "4d53c7cb27c0379adf8b51c4d3d0d2174f41d590" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "4d53c7cb27c0379adf8b51c4d3d0d2174f41d590" }

View File

@@ -176,7 +176,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
```yaml
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.0.208'
rev: 'v0.0.209'
hooks:
- id: ruff
# Respect `exclude` and `extend-exclude` settings.
@@ -277,7 +277,7 @@ alternative docstring formats. Enabling `ALL` without further configuration may
behavior, especially for the `pydocstyle` plugin.
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the above
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the
`pyproject.toml` described above would be represented via the following `ruff.toml`:
```toml
@@ -404,7 +404,7 @@ directory hierarchy is used for every individual file, with all paths in the `py
There are a few exceptions to these rules:
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignore any
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignores any
`pyproject.toml` files that lack a `[tool.ruff]` section.
2. If a configuration file is passed directly via `--config`, those settings are used for across
files. Any relative paths in that configuration file (like `exclude` globs or `src` paths) are
@@ -449,7 +449,7 @@ For example, `ruff /path/to/excluded/file.py` will always check `file.py`.
### Ignoring errors
To omit a lint check entirely, add it to the "ignore" list via [`ignore`](#ignore) or
[`extend-ignore`](#extend-ignore), either on the command-line or in your `project.toml` file.
[`extend-ignore`](#extend-ignore), either on the command-line or in your `pyproject.toml` file.
To ignore an error inline, Ruff uses a `noqa` system similar to [Flake8](https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html).
To ignore an individual error, add `# noqa: {code}` to the end of the line, like so:
@@ -960,7 +960,7 @@ For more, see [flake8-simplify](https://pypi.org/project/flake8-simplify/0.19.3/
| SIM118 | KeyInDict | Use `key in dict` instead of `key in dict.keys()` | 🛠 |
| SIM222 | OrTrue | Use `True` instead of `... or True` | 🛠 |
| SIM223 | AndFalse | Use `False` instead of `... and False` | 🛠 |
| SIM300 | YodaConditions | Use `left == right` instead of `right == left (Yoda-conditions)` | |
| SIM300 | YodaConditions | Use `left == right` instead of `right == left (Yoda-conditions)` | 🛠 |
### flake8-tidy-imports (TID)
@@ -1419,7 +1419,7 @@ Ruff can also replace [`isort`](https://pypi.org/project/isort/),
[`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10), and a subset of the rules
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (21/33).
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, free to file an Issue.
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an Issue.
### Do I need to install Rust to use Ruff?

View File

@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8_to_ruff"
version = "0.0.208"
version = "0.0.209"
dependencies = [
"anyhow",
"clap",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.208"
version = "0.0.209"
dependencies = [
"anyhow",
"bincode",

View File

@@ -1,6 +1,6 @@
[package]
name = "flake8-to-ruff"
version = "0.0.208-dev.0"
version = "0.0.209-dev.0"
edition = "2021"
[lib]

View File

@@ -4,7 +4,7 @@ build-backend = "maturin"
[project]
name = "ruff"
version = "0.0.208"
version = "0.0.209"
description = "An extremely fast Python linter, written in Rust."
authors = [
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },

View File

@@ -11,6 +11,11 @@ def test_csv(param1, param2):
...
@pytest.mark.parametrize(" param1, , param2 , ", [(1, 2), (3, 4)])
def test_csv_with_whitespace(param1, param2):
...
@pytest.mark.parametrize(("param1", "param2"), [(1, 2), (3, 4)])
def test_tuple(param1, param2):
...

View File

@@ -1,12 +1,14 @@
key in dict.keys() # SIM118
key in obj.keys() # SIM118
foo["bar"] in dict.keys() # SIM118
foo["bar"] in obj.keys() # SIM118
foo() in dict.keys() # SIM118
foo['bar'] in obj.keys() # SIM118
for key in dict.keys(): # SIM118
foo() in obj.keys() # SIM118
for key in obj.keys(): # SIM118
pass
for key in list(dict.keys()):
for key in list(obj.keys()):
if some_property(key):
del dict[key]
del obj[key]

View File

@@ -1,5 +1,6 @@
# Errors
"yoda" == compare # SIM300
'yoda' == compare # SIM300
42 == age # SIM300
# OK

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_dev"
version = "0.0.208"
version = "0.0.209"
edition = "2021"
[dependencies]

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_macros"
version = "0.0.208"
version = "0.0.209"
edition = "2021"
[lib]

View File

@@ -1,3 +1,4 @@
use log::error;
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
use crate::ast::types::Range;
@@ -53,13 +54,16 @@ pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option
checker.style.line_ending(),
);
generator.unparse_stmt(&assertion_error(msg));
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
stmt.location,
stmt.end_location.unwrap(),
));
}
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
stmt.location,
stmt.end_location.unwrap(),
));
}
Err(e) => error!("Failed to rewrite `assert False`: {e}"),
};
}
checker.add_check(check);
}

View File

@@ -1,4 +1,5 @@
use itertools::Itertools;
use log::error;
use rustc_hash::{FxHashMap, FxHashSet};
use rustpython_ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location};
@@ -64,12 +65,15 @@ fn duplicate_handler_exceptions<'a>(
} else {
generator.unparse_expr(&type_pattern(unique_elts), 0);
}
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
Err(e) => error!("Failed to remove duplicate exceptions: {e}"),
}
}
checker.add_check(check);

View File

@@ -1,3 +1,4 @@
use log::error;
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location};
use crate::ast::types::Range;
@@ -52,12 +53,15 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
checker.style.line_ending(),
);
generator.unparse_expr(&attribute(obj, value), 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
Err(e) => error!("Failed to rewrite `getattr`: {e}"),
}
}
checker.add_check(check);

View File

@@ -1,3 +1,4 @@
use log::error;
use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind};
use crate::ast::types::Range;
@@ -29,12 +30,15 @@ pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[E
checker.style.line_ending(),
);
generator.unparse_expr(elt, 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
type_.location,
type_.end_location.unwrap(),
));
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
type_.location,
type_.end_location.unwrap(),
));
}
Err(e) => error!("Failed to remove redundant tuple: {e}"),
}
}
checker.add_check(check);

View File

@@ -22,7 +22,19 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
value: Constant::Str(string),
..
} => {
let names = string.split(',').collect::<Vec<&str>>();
// Match the following pytest code:
// [x.strip() for x in argnames.split(",") if x.strip()]
let names = string
.split(',')
.filter_map(|s| {
let trimmed = s.trim();
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
})
.collect::<Vec<&str>>();
if names.len() > 1 {
match names_type {
@@ -193,13 +205,14 @@ pub fn parametrize(checker: &mut Checker, decorators: &[Expr]) {
if let Some(decorator) = decorator {
if let ExprKind::Call { args, .. } = &decorator.node {
if checker.settings.enabled.contains(&CheckCode::PT006) {
let first = args.first().unwrap();
check_names(checker, first);
if let Some(arg) = args.get(0) {
check_names(checker, arg);
}
}
if checker.settings.enabled.contains(&CheckCode::PT007) {
let second = args.get(1).unwrap();
check_values(checker, second);
if let Some(arg) = args.get(1) {
check_values(checker, arg);
}
}
}
}

View File

@@ -5,55 +5,55 @@ expression: checks
- kind:
ParametrizeNamesWrongType: csv
location:
row: 14
row: 19
column: 25
end_location:
row: 14
row: 19
column: 45
fix: ~
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 19
row: 24
column: 25
end_location:
row: 19
row: 24
column: 36
fix:
content: "\"param1\""
location:
row: 19
row: 24
column: 25
end_location:
row: 19
row: 24
column: 36
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 24
row: 29
column: 25
end_location:
row: 24
row: 29
column: 45
fix: ~
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
fix:
content: "\"param1\""
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
parent: ~

View File

@@ -20,47 +20,64 @@ expression: checks
column: 40
parent: ~
- kind:
ParametrizeNamesWrongType: csv
ParametrizeNamesWrongType: tuple
location:
row: 19
row: 14
column: 25
end_location:
row: 19
row: 14
column: 56
fix:
content: "(\"param1\", \"param2\")"
location:
row: 14
column: 25
end_location:
row: 14
column: 56
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 24
column: 25
end_location:
row: 24
column: 36
fix:
content: "\"param1\""
location:
row: 19
row: 24
column: 25
end_location:
row: 19
row: 24
column: 36
parent: ~
- kind:
ParametrizeNamesWrongType: tuple
location:
row: 24
row: 29
column: 25
end_location:
row: 24
row: 29
column: 45
fix: ~
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
fix:
content: "\"param1\""
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
parent: ~

View File

@@ -26,41 +26,58 @@ expression: checks
column: 25
end_location:
row: 14
column: 56
fix:
content: "[\"param1\", \"param2\"]"
location:
row: 14
column: 25
end_location:
row: 14
column: 56
parent: ~
- kind:
ParametrizeNamesWrongType: list
location:
row: 19
column: 25
end_location:
row: 19
column: 45
fix: ~
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 19
row: 24
column: 25
end_location:
row: 19
row: 24
column: 36
fix:
content: "\"param1\""
location:
row: 19
row: 24
column: 25
end_location:
row: 19
row: 24
column: 36
parent: ~
- kind:
ParametrizeNamesWrongType: csv
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
fix:
content: "\"param1\""
location:
row: 29
row: 34
column: 25
end_location:
row: 29
row: 34
column: 35
parent: ~

View File

@@ -1,11 +1,9 @@
use rustpython_ast::{Cmpop, Expr, ExprKind};
use crate::ast::helpers::create_expr;
use crate::ast::types::Range;
use crate::autofix::Fix;
use crate::checkers::ast::Checker;
use crate::registry::{Check, CheckKind};
use crate::source_code_generator::SourceCodeGenerator;
/// SIM118
fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: Range) {
@@ -27,25 +25,24 @@ fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: Range) {
return;
}
// Slice exact content to preserve formatting.
let left_content = checker
.locator
.slice_source_code_range(&Range::from_located(left));
let value_content = checker
.locator
.slice_source_code_range(&Range::from_located(value));
let mut check = Check::new(
CheckKind::KeyInDict(left.to_string(), value.to_string()),
CheckKind::KeyInDict(left_content.to_string(), value_content.to_string()),
range,
);
if checker.patch(check.kind.code()) {
let mut generator = SourceCodeGenerator::new(
checker.style.indentation(),
checker.style.quote(),
checker.style.line_ending(),
);
generator.unparse_expr(&create_expr(value.node.clone()), 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
right.location,
right.end_location.unwrap(),
));
}
check.amend(Fix::replacement(
value_content.to_string(),
right.location,
right.end_location.unwrap(),
));
}
checker.add_check(check);
}

View File

@@ -1,6 +1,7 @@
use rustpython_ast::{Cmpop, Expr, ExprKind};
use crate::ast::types::Range;
use crate::autofix::Fix;
use crate::checkers::ast::Checker;
use crate::registry::{Check, CheckKind};
@@ -31,10 +32,26 @@ pub fn yoda_conditions(
return;
}
let check = Check::new(
CheckKind::YodaConditions(left.to_string(), right.to_string()),
// Slice exact content to preserve formatting.
let left_content = checker
.locator
.slice_source_code_range(&Range::from_located(left));
let right_content = checker
.locator
.slice_source_code_range(&Range::from_located(right));
let mut check = Check::new(
CheckKind::YodaConditions(left_content.to_string(), right_content.to_string()),
Range::from_located(expr),
);
if checker.patch(check.kind.code()) {
check.amend(Fix::replacement(
format!("{right_content} == {left_content}"),
left.location,
right.end_location.unwrap(),
));
}
checker.add_check(check);
}

View File

@@ -5,77 +5,96 @@ expression: checks
- kind:
KeyInDict:
- key
- dict
- obj
location:
row: 1
column: 0
end_location:
row: 1
column: 18
column: 17
fix:
content: dict
content: obj
location:
row: 1
column: 7
end_location:
row: 1
column: 18
column: 17
parent: ~
- kind:
KeyInDict:
- "foo['bar']"
- dict
- "foo[\"bar\"]"
- obj
location:
row: 3
column: 0
end_location:
row: 3
column: 25
column: 24
fix:
content: dict
content: obj
location:
row: 3
column: 14
end_location:
row: 3
column: 25
column: 24
parent: ~
- kind:
KeyInDict:
- foo()
- dict
- "foo['bar']"
- obj
location:
row: 5
column: 0
end_location:
row: 5
column: 20
column: 24
fix:
content: dict
content: obj
location:
row: 5
column: 9
column: 14
end_location:
row: 5
column: 20
column: 24
parent: ~
- kind:
KeyInDict:
- foo()
- obj
location:
row: 7
column: 0
end_location:
row: 7
column: 19
fix:
content: obj
location:
row: 7
column: 9
end_location:
row: 7
column: 19
parent: ~
- kind:
KeyInDict:
- key
- dict
- obj
location:
row: 7
row: 9
column: 4
end_location:
row: 7
column: 22
row: 9
column: 21
fix:
content: dict
content: obj
location:
row: 7
row: 9
column: 11
end_location:
row: 7
column: 22
row: 9
column: 21
parent: ~

View File

@@ -4,7 +4,7 @@ expression: checks
---
- kind:
YodaConditions:
- "'yoda'"
- "\"yoda\""
- compare
location:
row: 2
@@ -12,18 +12,51 @@ expression: checks
end_location:
row: 2
column: 17
fix: ~
fix:
content: "compare == \"yoda\""
location:
row: 2
column: 0
end_location:
row: 2
column: 17
parent: ~
- kind:
YodaConditions:
- "'yoda'"
- compare
location:
row: 3
column: 0
end_location:
row: 3
column: 17
fix:
content: "compare == 'yoda'"
location:
row: 3
column: 0
end_location:
row: 3
column: 17
parent: ~
- kind:
YodaConditions:
- "42"
- age
location:
row: 3
row: 4
column: 0
end_location:
row: 3
row: 4
column: 9
fix: ~
fix:
content: age == 42
location:
row: 4
column: 0
end_location:
row: 4
column: 9
parent: ~

View File

@@ -1,5 +1,6 @@
use std::string::ToString;
use log::error;
use rustc_hash::FxHashSet;
use rustpython_ast::{Keyword, KeywordData};
use rustpython_parser::ast::{Constant, Expr, ExprKind};
@@ -115,9 +116,11 @@ pub(crate) fn percent_format_extra_named_arguments(
location,
);
if checker.patch(check.kind.code()) {
if let Ok(fix) = remove_unused_format_arguments_from_dict(&missing, right, checker.locator)
{
check.amend(fix);
match remove_unused_format_arguments_from_dict(&missing, right, checker.locator) {
Ok(fix) => {
check.amend(fix);
}
Err(e) => error!("Failed to remove unused format arguments: {e}"),
}
}
checker.add_check(check);
@@ -272,10 +275,12 @@ pub(crate) fn string_dot_format_extra_named_arguments(
location,
);
if checker.patch(check.kind.code()) {
if let Ok(fix) =
remove_unused_keyword_arguments_from_format_call(&missing, location, checker.locator)
match remove_unused_keyword_arguments_from_format_call(&missing, location, checker.locator)
{
check.amend(fix);
Ok(fix) => {
check.amend(fix);
}
Err(e) => error!("Failed to remove unused keyword arguments: {e}"),
}
}
checker.add_check(check);

View File

@@ -193,8 +193,8 @@ pub fn convert_named_tuple_functional_to_class(
return;
};
match match_defaults(keywords) {
Ok(defaults) => {
if let Ok(properties) = create_properties_from_args(args, defaults) {
Ok(defaults) => match create_properties_from_args(args, defaults) {
Ok(properties) => {
let mut check = Check::new(
CheckKind::ConvertNamedTupleFunctionalToClass(typename.to_string()),
Range::from_located(stmt),
@@ -209,7 +209,8 @@ pub fn convert_named_tuple_functional_to_class(
}
checker.add_check(check);
}
}
Err(err) => error!("Failed to create properties: {err}"),
},
Err(err) => error!("Failed to parse defaults: {err}"),
}
}

View File

@@ -1,3 +1,4 @@
use log::error;
use rustpython_ast::{Constant, Expr, ExprKind, Location, Operator};
use crate::ast::helpers::{collect_call_paths, dealias_call_path};
@@ -71,13 +72,16 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
checker.style.line_ending(),
);
generator.unparse_expr(&optional(slice), 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
Err(e) => error!("Failed to rewrite PEP604 annotation: {e}"),
};
}
checker.add_check(check);
} else if checker.match_typing_call_path(&call_path, "Union") {
@@ -94,12 +98,15 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
checker.style.line_ending(),
);
generator.unparse_expr(&union(elts), 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
Err(e) => error!("Failed to rewrite PEP604 annotation: {e}"),
}
}
_ => {
@@ -110,12 +117,15 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
checker.style.line_ending(),
);
generator.unparse_expr(slice, 0);
if let Ok(content) = generator.generate() {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
match generator.generate() {
Ok(content) => {
check.amend(Fix::replacement(
content,
expr.location,
expr.end_location.unwrap(),
));
}
Err(e) => error!("Failed to rewrite PEP604 annotation: {e}"),
}
}
}

View File

@@ -3594,6 +3594,7 @@ impl CheckKind {
| CheckKind::UselessImportAlias
| CheckKind::UselessMetaclassType
| CheckKind::UselessObjectInheritance(..)
| CheckKind::YodaConditions(..)
)
}
@@ -3856,6 +3857,9 @@ impl CheckKind {
CheckKind::UselessObjectInheritance(..) => {
Some("Remove `object` inheritance".to_string())
}
CheckKind::YodaConditions(left, right) => Some(format!(
"Replace with `{left} == {right}` (Yoda-conditions)`"
)),
_ => None,
}
}

View File

@@ -344,6 +344,7 @@ impl Hash for Settings {
self.flake8_bugbear.hash(state);
self.flake8_errmsg.hash(state);
self.flake8_import_conventions.hash(state);
self.flake8_pytest_style.hash(state);
self.flake8_quotes.hash(state);
self.flake8_tidy_imports.hash(state);
self.flake8_unused_arguments.hash(state);