mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 12:29:28 +00:00
Avoid adding return types to stub methods (#9277)
We should avoid adding `-> None` to stubs in `.pyi` files, along with a few other cases. (We already ignore abstract methods.) Closes https://github.com/astral-sh/ruff/issues/9270.
This commit is contained in:
parent
8b70240fa2
commit
fa78d2d97c
2 changed files with 85 additions and 55 deletions
|
@ -212,3 +212,20 @@ def func(x: int):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
else:
|
else:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def overloaded(i: int) -> "int":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def overloaded(i: "str") -> "str":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def overloaded(i):
|
||||||
|
return i
|
||||||
|
|
|
@ -482,7 +482,6 @@ impl Violation for AnyType {
|
||||||
format!("Dynamically typed expressions (typing.Any) are disallowed in `{name}`")
|
format!("Dynamically typed expressions (typing.Any) are disallowed in `{name}`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_none_returning(body: &[Stmt]) -> bool {
|
fn is_none_returning(body: &[Stmt]) -> bool {
|
||||||
let mut visitor = ReturnStatementVisitor::default();
|
let mut visitor = ReturnStatementVisitor::default();
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
|
@ -537,17 +536,41 @@ fn check_dynamically_typed<F>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty_body(body: &[Stmt]) -> bool {
|
/// Return `true` if a function appears to be a stub.
|
||||||
body.iter().all(|stmt| match stmt {
|
fn is_stub_function(function_def: &ast::StmtFunctionDef, checker: &Checker) -> bool {
|
||||||
Stmt::Pass(_) => true,
|
/// Returns `true` if a function has an empty body.
|
||||||
Stmt::Expr(ast::StmtExpr { value, range: _ }) => {
|
fn is_empty_body(function_def: &ast::StmtFunctionDef) -> bool {
|
||||||
matches!(
|
function_def.body.iter().all(|stmt| match stmt {
|
||||||
value.as_ref(),
|
Stmt::Pass(_) => true,
|
||||||
Expr::StringLiteral(_) | Expr::EllipsisLiteral(_)
|
Stmt::Expr(ast::StmtExpr { value, range: _ }) => {
|
||||||
)
|
matches!(
|
||||||
|
value.as_ref(),
|
||||||
|
Expr::StringLiteral(_) | Expr::EllipsisLiteral(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore functions with empty bodies in...
|
||||||
|
if is_empty_body(function_def) {
|
||||||
|
// Stub definitions (.pyi files)...
|
||||||
|
if checker.source_type.is_stub() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
_ => false,
|
|
||||||
})
|
// Abstract methods...
|
||||||
|
if visibility::is_abstract(&function_def.decorator_list, checker.semantic()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload definitions...
|
||||||
|
if visibility::is_overload(&function_def.decorator_list, checker.semantic()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate flake8-annotation checks for a given `Definition`.
|
/// Generate flake8-annotation checks for a given `Definition`.
|
||||||
|
@ -738,9 +761,7 @@ pub(crate) fn definition(
|
||||||
) {
|
) {
|
||||||
if is_method && visibility::is_classmethod(decorator_list, checker.semantic()) {
|
if is_method && visibility::is_classmethod(decorator_list, checker.semantic()) {
|
||||||
if checker.enabled(Rule::MissingReturnTypeClassMethod) {
|
if checker.enabled(Rule::MissingReturnTypeClassMethod) {
|
||||||
let return_type = if visibility::is_abstract(decorator_list, checker.semantic())
|
let return_type = if is_stub_function(function, checker) {
|
||||||
&& is_empty_body(body)
|
|
||||||
{
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
auto_return_type(function)
|
auto_return_type(function)
|
||||||
|
@ -771,9 +792,7 @@ pub(crate) fn definition(
|
||||||
}
|
}
|
||||||
} else if is_method && visibility::is_staticmethod(decorator_list, checker.semantic()) {
|
} else if is_method && visibility::is_staticmethod(decorator_list, checker.semantic()) {
|
||||||
if checker.enabled(Rule::MissingReturnTypeStaticMethod) {
|
if checker.enabled(Rule::MissingReturnTypeStaticMethod) {
|
||||||
let return_type = if visibility::is_abstract(decorator_list, checker.semantic())
|
let return_type = if is_stub_function(function, checker) {
|
||||||
&& is_empty_body(body)
|
|
||||||
{
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
auto_return_type(function)
|
auto_return_type(function)
|
||||||
|
@ -843,25 +862,22 @@ pub(crate) fn definition(
|
||||||
match visibility {
|
match visibility {
|
||||||
visibility::Visibility::Public => {
|
visibility::Visibility::Public => {
|
||||||
if checker.enabled(Rule::MissingReturnTypeUndocumentedPublicFunction) {
|
if checker.enabled(Rule::MissingReturnTypeUndocumentedPublicFunction) {
|
||||||
let return_type =
|
let return_type = if is_stub_function(function, checker) {
|
||||||
if visibility::is_abstract(decorator_list, checker.semantic())
|
None
|
||||||
&& is_empty_body(body)
|
} else {
|
||||||
{
|
auto_return_type(function)
|
||||||
None
|
.and_then(|return_type| {
|
||||||
} else {
|
return_type.into_expression(
|
||||||
auto_return_type(function)
|
checker.importer(),
|
||||||
.and_then(|return_type| {
|
function.parameters.start(),
|
||||||
return_type.into_expression(
|
checker.semantic(),
|
||||||
checker.importer(),
|
checker.settings.target_version,
|
||||||
function.parameters.start(),
|
)
|
||||||
checker.semantic(),
|
})
|
||||||
checker.settings.target_version,
|
.map(|(return_type, edits)| {
|
||||||
)
|
(checker.generator().expr(&return_type), edits)
|
||||||
})
|
})
|
||||||
.map(|(return_type, edits)| {
|
};
|
||||||
(checker.generator().expr(&return_type), edits)
|
|
||||||
})
|
|
||||||
};
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
MissingReturnTypeUndocumentedPublicFunction {
|
MissingReturnTypeUndocumentedPublicFunction {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
@ -885,25 +901,22 @@ pub(crate) fn definition(
|
||||||
}
|
}
|
||||||
visibility::Visibility::Private => {
|
visibility::Visibility::Private => {
|
||||||
if checker.enabled(Rule::MissingReturnTypePrivateFunction) {
|
if checker.enabled(Rule::MissingReturnTypePrivateFunction) {
|
||||||
let return_type =
|
let return_type = if is_stub_function(function, checker) {
|
||||||
if visibility::is_abstract(decorator_list, checker.semantic())
|
None
|
||||||
&& is_empty_body(body)
|
} else {
|
||||||
{
|
auto_return_type(function)
|
||||||
None
|
.and_then(|return_type| {
|
||||||
} else {
|
return_type.into_expression(
|
||||||
auto_return_type(function)
|
checker.importer(),
|
||||||
.and_then(|return_type| {
|
function.parameters.start(),
|
||||||
return_type.into_expression(
|
checker.semantic(),
|
||||||
checker.importer(),
|
checker.settings.target_version,
|
||||||
function.parameters.start(),
|
)
|
||||||
checker.semantic(),
|
})
|
||||||
checker.settings.target_version,
|
.map(|(return_type, edits)| {
|
||||||
)
|
(checker.generator().expr(&return_type), edits)
|
||||||
})
|
})
|
||||||
.map(|(return_type, edits)| {
|
};
|
||||||
(checker.generator().expr(&return_type), edits)
|
|
||||||
})
|
|
||||||
};
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
MissingReturnTypePrivateFunction {
|
MissingReturnTypePrivateFunction {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue