mirror of https://github.com/astral-sh/ruff
Implement F722
This commit is contained in:
parent
dfba1416b2
commit
00f82b11a9
|
|
@ -124,13 +124,13 @@ ruff's goal is to achieve feature-parity with Flake8 when used (1) without any p
|
||||||
stylistic checks; limiting to Python 3 obviates the need for certain compatibility checks.)
|
stylistic checks; limiting to Python 3 obviates the need for certain compatibility checks.)
|
||||||
|
|
||||||
Under those conditions, Flake8 implements about 60 rules, give or take. At time of writing, ruff
|
Under those conditions, Flake8 implements about 60 rules, give or take. At time of writing, ruff
|
||||||
implements 37 rules. (Note that these 37 rules likely cover a disproportionate share of errors:
|
implements 38 rules. (Note that these 38 rules likely cover a disproportionate share of errors:
|
||||||
unused imports, undefined variables, etc.)
|
unused imports, undefined variables, etc.)
|
||||||
|
|
||||||
The 23 unimplemented rules are tracked in #170, and include:
|
The unimplemented rules are tracked in #170, and include:
|
||||||
|
|
||||||
- 14 rules related to string `.format` calls.
|
- 14 rules related to string `.format` calls.
|
||||||
- 3 rules related to parsing and syntax errors.
|
- 1 rule related to parsing and syntax.
|
||||||
- 6 logical rules.
|
- 6 logical rules.
|
||||||
|
|
||||||
Beyond rule-set parity, ruff suffers from the following limitations vis-à-vis Flake8:
|
Beyond rule-set parity, ruff suffers from the following limitations vis-à-vis Flake8:
|
||||||
|
|
@ -172,6 +172,7 @@ Beyond rule-set parity, ruff suffers from the following limitations vis-à-vis F
|
||||||
| F704 | YieldOutsideFunction | a `yield` or `yield from` statement outside of a function/method |
|
| F704 | YieldOutsideFunction | a `yield` or `yield from` statement outside of a function/method |
|
||||||
| F706 | ReturnOutsideFunction | a `return` statement outside of a function/method |
|
| F706 | ReturnOutsideFunction | a `return` statement outside of a function/method |
|
||||||
| F707 | DefaultExceptNotLast | an `except:` block as not the last exception handler |
|
| F707 | DefaultExceptNotLast | an `except:` block as not the last exception handler |
|
||||||
|
| F722 | ForwardAnnotationSyntaxError | syntax error in forward annotation '...' |
|
||||||
| F821 | UndefinedName | Undefined name `...` |
|
| F821 | UndefinedName | Undefined name `...` |
|
||||||
| F822 | UndefinedExport | Undefined name `...` in `__all__` |
|
| F822 | UndefinedExport | Undefined name `...` in `__all__` |
|
||||||
| F823 | UndefinedLocal | Local variable `...` referenced before assignment |
|
| F823 | UndefinedLocal | Local variable `...` referenced before assignment |
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ fn main() {
|
||||||
CheckKind::DoNotAssignLambda,
|
CheckKind::DoNotAssignLambda,
|
||||||
CheckKind::DoNotUseBareExcept,
|
CheckKind::DoNotUseBareExcept,
|
||||||
CheckKind::DuplicateArgumentName,
|
CheckKind::DuplicateArgumentName,
|
||||||
|
CheckKind::ForwardAnnotationSyntaxError("...".to_string()),
|
||||||
CheckKind::FStringMissingPlaceholders,
|
CheckKind::FStringMissingPlaceholders,
|
||||||
CheckKind::FutureFeatureNotDefined("...".to_string()),
|
CheckKind::FutureFeatureNotDefined("...".to_string()),
|
||||||
CheckKind::IOError("...".to_string()),
|
CheckKind::IOError("...".to_string()),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
class A:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def f() -> "A":
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def g() -> "///":
|
||||||
|
pass
|
||||||
|
|
@ -31,6 +31,7 @@ select = [
|
||||||
"F704",
|
"F704",
|
||||||
"F706",
|
"F706",
|
||||||
"F707",
|
"F707",
|
||||||
|
"F722",
|
||||||
"F821",
|
"F821",
|
||||||
"F822",
|
"F822",
|
||||||
"F823",
|
"F823",
|
||||||
|
|
|
||||||
|
|
@ -1181,6 +1181,11 @@ impl<'a> Checker<'a> {
|
||||||
if let Ok(mut expr) = parser::parse_expression(expression, path) {
|
if let Ok(mut expr) = parser::parse_expression(expression, path) {
|
||||||
relocate_expr(&mut expr, location);
|
relocate_expr(&mut expr, location);
|
||||||
allocator.push(expr);
|
allocator.push(expr);
|
||||||
|
} else if self.settings.select.contains(&CheckCode::F722) {
|
||||||
|
self.checks.push(Check::new(
|
||||||
|
CheckKind::ForwardAnnotationSyntaxError(expression.to_string()),
|
||||||
|
location,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for expr in allocator {
|
for expr in allocator {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ pub enum CheckCode {
|
||||||
F704,
|
F704,
|
||||||
F706,
|
F706,
|
||||||
F707,
|
F707,
|
||||||
|
F722,
|
||||||
F821,
|
F821,
|
||||||
F822,
|
F822,
|
||||||
F823,
|
F823,
|
||||||
|
|
@ -126,6 +127,7 @@ impl CheckCode {
|
||||||
CheckCode::F704 => "F704",
|
CheckCode::F704 => "F704",
|
||||||
CheckCode::F706 => "F706",
|
CheckCode::F706 => "F706",
|
||||||
CheckCode::F707 => "F707",
|
CheckCode::F707 => "F707",
|
||||||
|
CheckCode::F722 => "F722",
|
||||||
CheckCode::F821 => "F821",
|
CheckCode::F821 => "F821",
|
||||||
CheckCode::F822 => "F822",
|
CheckCode::F822 => "F822",
|
||||||
CheckCode::F823 => "F823",
|
CheckCode::F823 => "F823",
|
||||||
|
|
@ -172,6 +174,7 @@ pub enum CheckKind {
|
||||||
DoNotAssignLambda,
|
DoNotAssignLambda,
|
||||||
DoNotUseBareExcept,
|
DoNotUseBareExcept,
|
||||||
DuplicateArgumentName,
|
DuplicateArgumentName,
|
||||||
|
ForwardAnnotationSyntaxError(String),
|
||||||
FStringMissingPlaceholders,
|
FStringMissingPlaceholders,
|
||||||
FutureFeatureNotDefined(String),
|
FutureFeatureNotDefined(String),
|
||||||
IOError(String),
|
IOError(String),
|
||||||
|
|
@ -215,6 +218,7 @@ impl CheckKind {
|
||||||
CheckKind::DoNotAssignLambda => "DoNotAssignLambda",
|
CheckKind::DoNotAssignLambda => "DoNotAssignLambda",
|
||||||
CheckKind::DoNotUseBareExcept => "DoNotUseBareExcept",
|
CheckKind::DoNotUseBareExcept => "DoNotUseBareExcept",
|
||||||
CheckKind::DuplicateArgumentName => "DuplicateArgumentName",
|
CheckKind::DuplicateArgumentName => "DuplicateArgumentName",
|
||||||
|
CheckKind::ForwardAnnotationSyntaxError(_) => "ForwardAnnotationSyntaxError",
|
||||||
CheckKind::FStringMissingPlaceholders => "FStringMissingPlaceholders",
|
CheckKind::FStringMissingPlaceholders => "FStringMissingPlaceholders",
|
||||||
CheckKind::FutureFeatureNotDefined(_) => "FutureFeatureNotDefined",
|
CheckKind::FutureFeatureNotDefined(_) => "FutureFeatureNotDefined",
|
||||||
CheckKind::IOError(_) => "IOError",
|
CheckKind::IOError(_) => "IOError",
|
||||||
|
|
@ -260,6 +264,7 @@ impl CheckKind {
|
||||||
CheckKind::DoNotAssignLambda => &CheckCode::E731,
|
CheckKind::DoNotAssignLambda => &CheckCode::E731,
|
||||||
CheckKind::DoNotUseBareExcept => &CheckCode::E722,
|
CheckKind::DoNotUseBareExcept => &CheckCode::E722,
|
||||||
CheckKind::DuplicateArgumentName => &CheckCode::F831,
|
CheckKind::DuplicateArgumentName => &CheckCode::F831,
|
||||||
|
CheckKind::ForwardAnnotationSyntaxError(_) => &CheckCode::F722,
|
||||||
CheckKind::FStringMissingPlaceholders => &CheckCode::F541,
|
CheckKind::FStringMissingPlaceholders => &CheckCode::F541,
|
||||||
CheckKind::FutureFeatureNotDefined(_) => &CheckCode::F407,
|
CheckKind::FutureFeatureNotDefined(_) => &CheckCode::F407,
|
||||||
CheckKind::IOError(_) => &CheckCode::E902,
|
CheckKind::IOError(_) => &CheckCode::E902,
|
||||||
|
|
@ -317,6 +322,9 @@ impl CheckKind {
|
||||||
CheckKind::DuplicateArgumentName => {
|
CheckKind::DuplicateArgumentName => {
|
||||||
"Duplicate argument name in function definition".to_string()
|
"Duplicate argument name in function definition".to_string()
|
||||||
}
|
}
|
||||||
|
CheckKind::ForwardAnnotationSyntaxError(body) => {
|
||||||
|
format!("syntax error in forward annotation '{body}'")
|
||||||
|
}
|
||||||
CheckKind::FStringMissingPlaceholders => {
|
CheckKind::FStringMissingPlaceholders => {
|
||||||
"f-string without any placeholders".to_string()
|
"f-string without any placeholders".to_string()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1073,6 +1073,31 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn f722() -> Result<()> {
|
||||||
|
let mut actual = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/F722.py"),
|
||||||
|
&settings::Settings {
|
||||||
|
line_length: 88,
|
||||||
|
exclude: vec![],
|
||||||
|
select: BTreeSet::from([CheckCode::F722]),
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
|
let expected = vec![Check {
|
||||||
|
kind: CheckKind::ForwardAnnotationSyntaxError("///".to_string()),
|
||||||
|
location: Location::new(9, 13),
|
||||||
|
fix: None,
|
||||||
|
}];
|
||||||
|
assert_eq!(actual.len(), expected.len());
|
||||||
|
for i in 0..actual.len() {
|
||||||
|
assert_eq!(actual[i], expected[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f821() -> Result<()> {
|
fn f821() -> Result<()> {
|
||||||
let mut actual = check_path(
|
let mut actual = check_path(
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,7 @@ other-attribute = 1
|
||||||
CheckCode::F704,
|
CheckCode::F704,
|
||||||
CheckCode::F706,
|
CheckCode::F706,
|
||||||
CheckCode::F707,
|
CheckCode::F707,
|
||||||
|
CheckCode::F722,
|
||||||
CheckCode::F821,
|
CheckCode::F821,
|
||||||
CheckCode::F822,
|
CheckCode::F822,
|
||||||
CheckCode::F823,
|
CheckCode::F823,
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ impl Settings {
|
||||||
CheckCode::F704,
|
CheckCode::F704,
|
||||||
CheckCode::F706,
|
CheckCode::F706,
|
||||||
CheckCode::F707,
|
CheckCode::F707,
|
||||||
|
CheckCode::F722,
|
||||||
CheckCode::F821,
|
CheckCode::F821,
|
||||||
CheckCode::F822,
|
CheckCode::F822,
|
||||||
CheckCode::F823,
|
CheckCode::F823,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue