mirror of https://github.com/astral-sh/ruff
Implement ANN401 (#657)
This commit is contained in:
parent
2ddc768412
commit
24aa177912
|
|
@ -546,6 +546,7 @@ For more, see [flake8-annotations](https://pypi.org/project/flake8-annotations/2
|
||||||
| ANN204 | MissingReturnTypeMagicMethod | Missing return type annotation for magic method `...` | |
|
| ANN204 | MissingReturnTypeMagicMethod | Missing return type annotation for magic method `...` | |
|
||||||
| ANN205 | MissingReturnTypeStaticMethod | Missing return type annotation for staticmethod `...` | |
|
| ANN205 | MissingReturnTypeStaticMethod | Missing return type annotation for staticmethod `...` | |
|
||||||
| ANN206 | MissingReturnTypeClassMethod | Missing return type annotation for classmethod `...` | |
|
| ANN206 | MissingReturnTypeClassMethod | Missing return type annotation for classmethod `...` | |
|
||||||
|
| ANN401 | DynamicallyTypedExpression | Dynamically typed expressions (typing.Any) are disallowed in `...` | |
|
||||||
|
|
||||||
### Ruff-specific rules
|
### Ruff-specific rules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo(a: int, *args: str, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: Any, *args: str, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: str, **kwargs: str) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo(a: int, *args: Any, **kwargs: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo(a: int, *args: Any, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: str, **kwargs: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Bar:
|
||||||
|
# OK
|
||||||
|
def foo_method(self, a: int, *params: str, **options: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo_method(self, a: Any, *params: str, **options: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo_method(self, a: int, *params: str, **options: str) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo_method(self, a: int, *params: Any, **options: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo_method(self, a: int, *params: Any, **options: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo_method(self, a: int, *params: str, **options: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Type
|
from typing import Any, Type
|
||||||
|
|
||||||
# Error
|
# Error
|
||||||
def foo(a, b):
|
def foo(a, b):
|
||||||
|
|
@ -35,6 +35,36 @@ def foo() -> int:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def foo(a: int, *args: str, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: Any, *args: str, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: str, **kwargs: str) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: Any, **kwargs: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: Any, **kwargs: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(a: int, *args: str, **kwargs: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
class Foo:
|
||||||
# OK
|
# OK
|
||||||
def foo(self: "Foo", a: int, b: int) -> int:
|
def foo(self: "Foo", a: int, b: int) -> int:
|
||||||
|
|
@ -44,6 +74,26 @@ class Foo:
|
||||||
def foo(self, a: int, b: int) -> int:
|
def foo(self, a: int, b: int) -> int:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(self: "Foo", a: Any, *params: str, **options: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(self: "Foo", a: int, *params: str, **options: str) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(self: "Foo", a: int, *params: Any, **options: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(self: "Foo", a: int, *params: Any, **options: str) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ANN401
|
||||||
|
def foo(self: "Foo", a: int, *params: str, **options: Any) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
# OK
|
# OK
|
||||||
@classmethod
|
@classmethod
|
||||||
def foo(cls: Type["Foo"], a: int, b: int) -> int:
|
def foo(cls: Type["Foo"], a: int, b: int) -> int:
|
||||||
|
|
|
||||||
|
|
@ -2408,6 +2408,7 @@ impl<'a> Checker<'a> {
|
||||||
|| self.settings.enabled.contains(&CheckCode::ANN204)
|
|| self.settings.enabled.contains(&CheckCode::ANN204)
|
||||||
|| self.settings.enabled.contains(&CheckCode::ANN205)
|
|| self.settings.enabled.contains(&CheckCode::ANN205)
|
||||||
|| self.settings.enabled.contains(&CheckCode::ANN206)
|
|| self.settings.enabled.contains(&CheckCode::ANN206)
|
||||||
|
|| self.settings.enabled.contains(&CheckCode::ANN401)
|
||||||
{
|
{
|
||||||
flake8_annotations::plugins::definition(self, &definition, &visibility);
|
flake8_annotations::plugins::definition(self, &definition, &visibility);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ pub enum CheckCode {
|
||||||
ANN204,
|
ANN204,
|
||||||
ANN205,
|
ANN205,
|
||||||
ANN206,
|
ANN206,
|
||||||
|
ANN401,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
U001,
|
U001,
|
||||||
U002,
|
U002,
|
||||||
|
|
@ -390,6 +391,7 @@ pub enum CheckKind {
|
||||||
MissingReturnTypeMagicMethod(String),
|
MissingReturnTypeMagicMethod(String),
|
||||||
MissingReturnTypeStaticMethod(String),
|
MissingReturnTypeStaticMethod(String),
|
||||||
MissingReturnTypeClassMethod(String),
|
MissingReturnTypeClassMethod(String),
|
||||||
|
DynamicallyTypedExpression(String),
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
TypeOfPrimitive(Primitive),
|
TypeOfPrimitive(Primitive),
|
||||||
UnnecessaryAbspath,
|
UnnecessaryAbspath,
|
||||||
|
|
@ -614,6 +616,7 @@ impl CheckCode {
|
||||||
CheckCode::ANN204 => CheckKind::MissingReturnTypeMagicMethod("...".to_string()),
|
CheckCode::ANN204 => CheckKind::MissingReturnTypeMagicMethod("...".to_string()),
|
||||||
CheckCode::ANN205 => CheckKind::MissingReturnTypeStaticMethod("...".to_string()),
|
CheckCode::ANN205 => CheckKind::MissingReturnTypeStaticMethod("...".to_string()),
|
||||||
CheckCode::ANN206 => CheckKind::MissingReturnTypeClassMethod("...".to_string()),
|
CheckCode::ANN206 => CheckKind::MissingReturnTypeClassMethod("...".to_string()),
|
||||||
|
CheckCode::ANN401 => CheckKind::DynamicallyTypedExpression("...".to_string()),
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckCode::U001 => CheckKind::UselessMetaclassType,
|
CheckCode::U001 => CheckKind::UselessMetaclassType,
|
||||||
CheckCode::U002 => CheckKind::UnnecessaryAbspath,
|
CheckCode::U002 => CheckKind::UnnecessaryAbspath,
|
||||||
|
|
@ -810,6 +813,7 @@ impl CheckCode {
|
||||||
CheckCode::ANN204 => CheckCategory::Flake8Annotations,
|
CheckCode::ANN204 => CheckCategory::Flake8Annotations,
|
||||||
CheckCode::ANN205 => CheckCategory::Flake8Annotations,
|
CheckCode::ANN205 => CheckCategory::Flake8Annotations,
|
||||||
CheckCode::ANN206 => CheckCategory::Flake8Annotations,
|
CheckCode::ANN206 => CheckCategory::Flake8Annotations,
|
||||||
|
CheckCode::ANN401 => CheckCategory::Flake8Annotations,
|
||||||
CheckCode::U001 => CheckCategory::Pyupgrade,
|
CheckCode::U001 => CheckCategory::Pyupgrade,
|
||||||
CheckCode::U002 => CheckCategory::Pyupgrade,
|
CheckCode::U002 => CheckCategory::Pyupgrade,
|
||||||
CheckCode::U003 => CheckCategory::Pyupgrade,
|
CheckCode::U003 => CheckCategory::Pyupgrade,
|
||||||
|
|
@ -993,6 +997,7 @@ impl CheckKind {
|
||||||
CheckKind::MissingReturnTypeMagicMethod(_) => &CheckCode::ANN204,
|
CheckKind::MissingReturnTypeMagicMethod(_) => &CheckCode::ANN204,
|
||||||
CheckKind::MissingReturnTypeStaticMethod(_) => &CheckCode::ANN205,
|
CheckKind::MissingReturnTypeStaticMethod(_) => &CheckCode::ANN205,
|
||||||
CheckKind::MissingReturnTypeClassMethod(_) => &CheckCode::ANN206,
|
CheckKind::MissingReturnTypeClassMethod(_) => &CheckCode::ANN206,
|
||||||
|
CheckKind::DynamicallyTypedExpression(_) => &CheckCode::ANN401,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckKind::TypeOfPrimitive(_) => &CheckCode::U003,
|
CheckKind::TypeOfPrimitive(_) => &CheckCode::U003,
|
||||||
CheckKind::UnnecessaryAbspath => &CheckCode::U002,
|
CheckKind::UnnecessaryAbspath => &CheckCode::U002,
|
||||||
|
|
@ -1416,6 +1421,9 @@ impl CheckKind {
|
||||||
CheckKind::MissingReturnTypeClassMethod(name) => {
|
CheckKind::MissingReturnTypeClassMethod(name) => {
|
||||||
format!("Missing return type annotation for classmethod `{name}`")
|
format!("Missing return type annotation for classmethod `{name}`")
|
||||||
}
|
}
|
||||||
|
CheckKind::DynamicallyTypedExpression(name) => {
|
||||||
|
format!("Dynamically typed expressions (typing.Any) are disallowed in `{name}`")
|
||||||
|
}
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckKind::TypeOfPrimitive(primitive) => {
|
CheckKind::TypeOfPrimitive(primitive) => {
|
||||||
format!("Use `{}` instead of `type(...)`", primitive.builtin())
|
format!("Use `{}` instead of `type(...)`", primitive.builtin())
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ pub enum CheckCodePrefix {
|
||||||
ANN204,
|
ANN204,
|
||||||
ANN205,
|
ANN205,
|
||||||
ANN206,
|
ANN206,
|
||||||
|
ANN4,
|
||||||
|
ANN40,
|
||||||
|
ANN401,
|
||||||
B,
|
B,
|
||||||
B0,
|
B0,
|
||||||
B00,
|
B00,
|
||||||
|
|
@ -290,6 +293,7 @@ impl CheckCodePrefix {
|
||||||
CheckCode::ANN204,
|
CheckCode::ANN204,
|
||||||
CheckCode::ANN205,
|
CheckCode::ANN205,
|
||||||
CheckCode::ANN206,
|
CheckCode::ANN206,
|
||||||
|
CheckCode::ANN401,
|
||||||
],
|
],
|
||||||
CheckCodePrefix::ANN0 => vec![CheckCode::ANN001, CheckCode::ANN002, CheckCode::ANN003],
|
CheckCodePrefix::ANN0 => vec![CheckCode::ANN001, CheckCode::ANN002, CheckCode::ANN003],
|
||||||
CheckCodePrefix::ANN00 => vec![CheckCode::ANN001, CheckCode::ANN002, CheckCode::ANN003],
|
CheckCodePrefix::ANN00 => vec![CheckCode::ANN001, CheckCode::ANN002, CheckCode::ANN003],
|
||||||
|
|
@ -319,6 +323,9 @@ impl CheckCodePrefix {
|
||||||
CheckCodePrefix::ANN204 => vec![CheckCode::ANN204],
|
CheckCodePrefix::ANN204 => vec![CheckCode::ANN204],
|
||||||
CheckCodePrefix::ANN205 => vec![CheckCode::ANN205],
|
CheckCodePrefix::ANN205 => vec![CheckCode::ANN205],
|
||||||
CheckCodePrefix::ANN206 => vec![CheckCode::ANN206],
|
CheckCodePrefix::ANN206 => vec![CheckCode::ANN206],
|
||||||
|
CheckCodePrefix::ANN4 => vec![CheckCode::ANN401],
|
||||||
|
CheckCodePrefix::ANN40 => vec![CheckCode::ANN401],
|
||||||
|
CheckCodePrefix::ANN401 => vec![CheckCode::ANN401],
|
||||||
CheckCodePrefix::B => vec![
|
CheckCodePrefix::B => vec![
|
||||||
CheckCode::B002,
|
CheckCode::B002,
|
||||||
CheckCode::B003,
|
CheckCode::B003,
|
||||||
|
|
@ -1023,6 +1030,9 @@ impl CheckCodePrefix {
|
||||||
CheckCodePrefix::ANN204 => PrefixSpecificity::Explicit,
|
CheckCodePrefix::ANN204 => PrefixSpecificity::Explicit,
|
||||||
CheckCodePrefix::ANN205 => PrefixSpecificity::Explicit,
|
CheckCodePrefix::ANN205 => PrefixSpecificity::Explicit,
|
||||||
CheckCodePrefix::ANN206 => PrefixSpecificity::Explicit,
|
CheckCodePrefix::ANN206 => PrefixSpecificity::Explicit,
|
||||||
|
CheckCodePrefix::ANN4 => PrefixSpecificity::Hundreds,
|
||||||
|
CheckCodePrefix::ANN40 => PrefixSpecificity::Tens,
|
||||||
|
CheckCodePrefix::ANN401 => PrefixSpecificity::Explicit,
|
||||||
CheckCodePrefix::B => PrefixSpecificity::Category,
|
CheckCodePrefix::B => PrefixSpecificity::Category,
|
||||||
CheckCodePrefix::B0 => PrefixSpecificity::Hundreds,
|
CheckCodePrefix::B0 => PrefixSpecificity::Hundreds,
|
||||||
CheckCodePrefix::B00 => PrefixSpecificity::Tens,
|
CheckCodePrefix::B00 => PrefixSpecificity::Tens,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ mod tests {
|
||||||
CheckCode::ANN204,
|
CheckCode::ANN204,
|
||||||
CheckCode::ANN205,
|
CheckCode::ANN205,
|
||||||
CheckCode::ANN206,
|
CheckCode::ANN206,
|
||||||
|
CheckCode::ANN401,
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
&fixer::Mode::Generate,
|
&fixer::Mode::Generate,
|
||||||
|
|
@ -63,6 +64,7 @@ mod tests {
|
||||||
mypy_init_return: false,
|
mypy_init_return: false,
|
||||||
suppress_dummy_args: true,
|
suppress_dummy_args: true,
|
||||||
suppress_none_returning: false,
|
suppress_none_returning: false,
|
||||||
|
allow_star_arg_any: false,
|
||||||
},
|
},
|
||||||
..Settings::for_rules(vec![
|
..Settings::for_rules(vec![
|
||||||
CheckCode::ANN001,
|
CheckCode::ANN001,
|
||||||
|
|
@ -88,6 +90,7 @@ mod tests {
|
||||||
mypy_init_return: true,
|
mypy_init_return: true,
|
||||||
suppress_dummy_args: false,
|
suppress_dummy_args: false,
|
||||||
suppress_none_returning: false,
|
suppress_none_returning: false,
|
||||||
|
allow_star_arg_any: false,
|
||||||
},
|
},
|
||||||
..Settings::for_rules(vec![
|
..Settings::for_rules(vec![
|
||||||
CheckCode::ANN201,
|
CheckCode::ANN201,
|
||||||
|
|
@ -113,6 +116,7 @@ mod tests {
|
||||||
mypy_init_return: false,
|
mypy_init_return: false,
|
||||||
suppress_dummy_args: false,
|
suppress_dummy_args: false,
|
||||||
suppress_none_returning: true,
|
suppress_none_returning: true,
|
||||||
|
allow_star_arg_any: false,
|
||||||
},
|
},
|
||||||
..Settings::for_rules(vec![
|
..Settings::for_rules(vec![
|
||||||
CheckCode::ANN201,
|
CheckCode::ANN201,
|
||||||
|
|
@ -128,4 +132,24 @@ mod tests {
|
||||||
insta::assert_yaml_snapshot!(checks);
|
insta::assert_yaml_snapshot!(checks);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn allow_star_arg_any() -> Result<()> {
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/flake8_annotations/allow_star_arg_any.py"),
|
||||||
|
&Settings {
|
||||||
|
flake8_annotations: flake8_annotations::settings::Settings {
|
||||||
|
mypy_init_return: false,
|
||||||
|
suppress_dummy_args: false,
|
||||||
|
suppress_none_returning: false,
|
||||||
|
allow_star_arg_any: true,
|
||||||
|
},
|
||||||
|
..Settings::for_rules(vec![CheckCode::ANN401])
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ fn is_none_returning(body: &[Stmt]) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ANN401
|
||||||
|
fn check_dynamically_typed(checker: &mut Checker, annotation: &Expr, name: &str) {
|
||||||
|
if checker.match_typing_module(annotation, "Any") {
|
||||||
|
checker.add_check(Check::new(
|
||||||
|
CheckKind::DynamicallyTypedExpression(name.to_string()),
|
||||||
|
Range::from_located(annotation),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, &Option<Box<Expr>>, &Vec<Stmt>) {
|
fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, &Option<Box<Expr>>, &Vec<Stmt>) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef {
|
StmtKind::FunctionDef {
|
||||||
|
|
@ -81,14 +91,18 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
DefinitionKind::Function(stmt) | DefinitionKind::NestedFunction(stmt) => {
|
DefinitionKind::Function(stmt) | DefinitionKind::NestedFunction(stmt) => {
|
||||||
let (name, args, returns, body) = match_function_def(stmt);
|
let (name, args, returns, body) = match_function_def(stmt);
|
||||||
|
|
||||||
// ANN001
|
// ANN001, ANN401
|
||||||
for arg in args
|
for arg in args
|
||||||
.args
|
.args
|
||||||
.iter()
|
.iter()
|
||||||
.chain(args.posonlyargs.iter())
|
.chain(args.posonlyargs.iter())
|
||||||
.chain(args.kwonlyargs.iter())
|
.chain(args.kwonlyargs.iter())
|
||||||
{
|
{
|
||||||
if arg.node.annotation.is_none() {
|
if let Some(expr) = &arg.node.annotation {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
check_dynamically_typed(checker, expr, &arg.node.arg);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -102,9 +116,16 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN002
|
// ANN002, ANN401
|
||||||
if let Some(arg) = &args.vararg {
|
if let Some(arg) = &args.vararg {
|
||||||
if arg.node.annotation.is_none() {
|
if let Some(expr) = &arg.node.annotation {
|
||||||
|
if !checker.settings.flake8_annotations.allow_star_arg_any {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
let name = arg.node.arg.to_string();
|
||||||
|
check_dynamically_typed(checker, expr, &format!("*{name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -118,9 +139,16 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN003
|
// ANN003, ANN401
|
||||||
if let Some(arg) = &args.kwarg {
|
if let Some(arg) = &args.kwarg {
|
||||||
if arg.node.annotation.is_none() {
|
if let Some(expr) = &arg.node.annotation {
|
||||||
|
if !checker.settings.flake8_annotations.allow_star_arg_any {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
let name = arg.node.arg.to_string();
|
||||||
|
check_dynamically_typed(checker, expr, &format!("**{name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -134,8 +162,12 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN201, ANN202
|
// ANN201, ANN202, ANN401
|
||||||
if returns.is_none() {
|
if let Some(expr) = &returns {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
check_dynamically_typed(checker, expr, name);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
// Allow omission of return annotation in `__init__` functions, if the function
|
// Allow omission of return annotation in `__init__` functions, if the function
|
||||||
// only returns `None` (explicitly or implicitly).
|
// only returns `None` (explicitly or implicitly).
|
||||||
if checker.settings.flake8_annotations.suppress_none_returning
|
if checker.settings.flake8_annotations.suppress_none_returning
|
||||||
|
|
@ -179,7 +211,13 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
usize::from(!visibility::is_staticmethod(stmt)),
|
usize::from(!visibility::is_staticmethod(stmt)),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if arg.node.annotation.is_none() {
|
// ANN401 for dynamically typed arguments
|
||||||
|
if let Some(annotation) = &arg.node.annotation {
|
||||||
|
has_any_typed_arg = true;
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
check_dynamically_typed(checker, annotation, &arg.node.arg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -190,14 +228,20 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
has_any_typed_arg = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN002
|
// ANN002, ANN401
|
||||||
if let Some(arg) = &args.vararg {
|
if let Some(arg) = &args.vararg {
|
||||||
if arg.node.annotation.is_none() {
|
has_any_typed_arg = true;
|
||||||
|
if let Some(expr) = &arg.node.annotation {
|
||||||
|
if !checker.settings.flake8_annotations.allow_star_arg_any {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
let name = arg.node.arg.to_string();
|
||||||
|
check_dynamically_typed(checker, expr, &format!("*{name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -208,14 +252,20 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
has_any_typed_arg = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN003
|
// ANN003, ANN401
|
||||||
if let Some(arg) = &args.kwarg {
|
if let Some(arg) = &args.kwarg {
|
||||||
if arg.node.annotation.is_none() {
|
has_any_typed_arg = true;
|
||||||
|
if let Some(expr) = &arg.node.annotation {
|
||||||
|
if !checker.settings.flake8_annotations.allow_star_arg_any {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
let name = arg.node.arg.to_string();
|
||||||
|
check_dynamically_typed(checker, expr, &format!("**{name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
if !(checker.settings.flake8_annotations.suppress_dummy_args
|
||||||
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
|
||||||
{
|
{
|
||||||
|
|
@ -226,8 +276,6 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
has_any_typed_arg = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,7 +303,11 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANN201, ANN202
|
// ANN201, ANN202
|
||||||
if returns.is_none() {
|
if let Some(expr) = &returns {
|
||||||
|
if checker.settings.enabled.contains(&CheckCode::ANN401) {
|
||||||
|
check_dynamically_typed(checker, expr, name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Allow omission of return annotation in `__init__` functions, if the function
|
// Allow omission of return annotation in `__init__` functions, if the function
|
||||||
// only returns `None` (explicitly or implicitly).
|
// only returns `None` (explicitly or implicitly).
|
||||||
if checker.settings.flake8_annotations.suppress_none_returning
|
if checker.settings.flake8_annotations.suppress_none_returning
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ pub struct Options {
|
||||||
/// - Explicit `return` statement(s) all return `None` (explicitly or
|
/// - Explicit `return` statement(s) all return `None` (explicitly or
|
||||||
/// implicitly).
|
/// implicitly).
|
||||||
pub suppress_none_returning: Option<bool>,
|
pub suppress_none_returning: Option<bool>,
|
||||||
|
/// Suppress ANN401 for dynamically typed *args and **kwargs.
|
||||||
|
pub allow_star_arg_any: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash, Default)]
|
#[derive(Debug, Hash, Default)]
|
||||||
|
|
@ -23,6 +25,7 @@ pub struct Settings {
|
||||||
pub mypy_init_return: bool,
|
pub mypy_init_return: bool,
|
||||||
pub suppress_dummy_args: bool,
|
pub suppress_dummy_args: bool,
|
||||||
pub suppress_none_returning: bool,
|
pub suppress_none_returning: bool,
|
||||||
|
pub allow_star_arg_any: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
|
|
@ -31,6 +34,7 @@ impl Settings {
|
||||||
mypy_init_return: options.mypy_init_return.unwrap_or_default(),
|
mypy_init_return: options.mypy_init_return.unwrap_or_default(),
|
||||||
suppress_dummy_args: options.suppress_dummy_args.unwrap_or_default(),
|
suppress_dummy_args: options.suppress_dummy_args.unwrap_or_default(),
|
||||||
suppress_none_returning: options.suppress_none_returning.unwrap_or_default(),
|
suppress_none_returning: options.suppress_none_returning.unwrap_or_default(),
|
||||||
|
allow_star_arg_any: options.allow_star_arg_any.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_annotations/mod.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: a
|
||||||
|
location:
|
||||||
|
row: 10
|
||||||
|
column: 11
|
||||||
|
end_location:
|
||||||
|
row: 10
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: foo
|
||||||
|
location:
|
||||||
|
row: 15
|
||||||
|
column: 46
|
||||||
|
end_location:
|
||||||
|
row: 15
|
||||||
|
column: 49
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: a
|
||||||
|
location:
|
||||||
|
row: 40
|
||||||
|
column: 28
|
||||||
|
end_location:
|
||||||
|
row: 40
|
||||||
|
column: 31
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: foo_method
|
||||||
|
location:
|
||||||
|
row: 44
|
||||||
|
column: 66
|
||||||
|
end_location:
|
||||||
|
row: 44
|
||||||
|
column: 69
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -75,21 +75,129 @@ expression: checks
|
||||||
column: 0
|
column: 0
|
||||||
fix: ~
|
fix: ~
|
||||||
- kind:
|
- kind:
|
||||||
MissingTypeSelf: self
|
DynamicallyTypedExpression: a
|
||||||
location:
|
location:
|
||||||
row: 44
|
row: 44
|
||||||
column: 12
|
column: 11
|
||||||
end_location:
|
end_location:
|
||||||
row: 44
|
row: 44
|
||||||
|
column: 14
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: foo
|
||||||
|
location:
|
||||||
|
row: 49
|
||||||
|
column: 46
|
||||||
|
end_location:
|
||||||
|
row: 49
|
||||||
|
column: 49
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "*args"
|
||||||
|
location:
|
||||||
|
row: 54
|
||||||
|
column: 23
|
||||||
|
end_location:
|
||||||
|
row: 54
|
||||||
|
column: 26
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "**kwargs"
|
||||||
|
location:
|
||||||
|
row: 54
|
||||||
|
column: 38
|
||||||
|
end_location:
|
||||||
|
row: 54
|
||||||
|
column: 41
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "*args"
|
||||||
|
location:
|
||||||
|
row: 59
|
||||||
|
column: 23
|
||||||
|
end_location:
|
||||||
|
row: 59
|
||||||
|
column: 26
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "**kwargs"
|
||||||
|
location:
|
||||||
|
row: 64
|
||||||
|
column: 38
|
||||||
|
end_location:
|
||||||
|
row: 64
|
||||||
|
column: 41
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
MissingTypeSelf: self
|
||||||
|
location:
|
||||||
|
row: 74
|
||||||
|
column: 12
|
||||||
|
end_location:
|
||||||
|
row: 74
|
||||||
column: 16
|
column: 16
|
||||||
fix: ~
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: a
|
||||||
|
location:
|
||||||
|
row: 78
|
||||||
|
column: 28
|
||||||
|
end_location:
|
||||||
|
row: 78
|
||||||
|
column: 31
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: foo
|
||||||
|
location:
|
||||||
|
row: 82
|
||||||
|
column: 66
|
||||||
|
end_location:
|
||||||
|
row: 82
|
||||||
|
column: 69
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "*params"
|
||||||
|
location:
|
||||||
|
row: 86
|
||||||
|
column: 42
|
||||||
|
end_location:
|
||||||
|
row: 86
|
||||||
|
column: 45
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "**options"
|
||||||
|
location:
|
||||||
|
row: 86
|
||||||
|
column: 58
|
||||||
|
end_location:
|
||||||
|
row: 86
|
||||||
|
column: 61
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "*params"
|
||||||
|
location:
|
||||||
|
row: 90
|
||||||
|
column: 42
|
||||||
|
end_location:
|
||||||
|
row: 90
|
||||||
|
column: 45
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
DynamicallyTypedExpression: "**options"
|
||||||
|
location:
|
||||||
|
row: 94
|
||||||
|
column: 58
|
||||||
|
end_location:
|
||||||
|
row: 94
|
||||||
|
column: 61
|
||||||
|
fix: ~
|
||||||
- kind:
|
- kind:
|
||||||
MissingTypeCls: cls
|
MissingTypeCls: cls
|
||||||
location:
|
location:
|
||||||
row: 54
|
row: 104
|
||||||
column: 12
|
column: 12
|
||||||
end_location:
|
end_location:
|
||||||
row: 54
|
row: 104
|
||||||
column: 15
|
column: 15
|
||||||
fix: ~
|
fix: ~
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue