Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9a236f740 | ||
|
|
ebb31dc29b | ||
|
|
b9e92affb1 | ||
|
|
68fbd0f029 | ||
|
|
8d01efb571 | ||
|
|
da5a25b421 | ||
|
|
bfdab4ac94 | ||
|
|
d1389894a4 |
@@ -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
8
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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" }
|
||||
|
||||
12
README.md
12
README.md
@@ -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?
|
||||
|
||||
|
||||
4
flake8_to_ruff/Cargo.lock
generated
4
flake8_to_ruff/Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.208-dev.0"
|
||||
version = "0.0.209-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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):
|
||||
...
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Errors
|
||||
"yoda" == compare # SIM300
|
||||
'yoda' == compare # SIM300
|
||||
42 == age # SIM300
|
||||
|
||||
# OK
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.208"
|
||||
version = "0.0.209"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.208"
|
||||
version = "0.0.209"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: ~
|
||||
|
||||
|
||||
@@ -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: ~
|
||||
|
||||
|
||||
@@ -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: ~
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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: ~
|
||||
|
||||
|
||||
@@ -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: ~
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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}"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user