Exempt `PLR1711` and `RET501` if non-`None` annotation (#3705)

This commit is contained in:
Jonathan Plasse 2023-03-24 04:11:58 +01:00 committed by GitHub
parent 7f3b748401
commit efc6e8cb39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 91 additions and 10 deletions

View File

@ -2,3 +2,13 @@ def x(y):
if not y: if not y:
return return
return None # error return None # error
class BaseCache:
def get(self, key: str) -> str | None:
print(f"{key} not found")
return None
def get(self, key: str) -> None:
print(f"{key} not found")
return None

View File

@ -48,3 +48,13 @@ def print_python_version():
"""This function returns None.""" """This function returns None."""
print(sys.version) print(sys.version)
return None # [useless-return] return None # [useless-return]
class BaseCache:
def get(self, key: str) -> str | None:
print(f"{key} not found")
return None
def get(self, key: str) -> None:
print(f"{key} not found")
return None

View File

@ -434,11 +434,20 @@ where
Rule::SuperfluousElseContinue, Rule::SuperfluousElseContinue,
Rule::SuperfluousElseBreak, Rule::SuperfluousElseBreak,
]) { ]) {
flake8_return::rules::function(self, body); flake8_return::rules::function(
self,
body,
returns.as_ref().map(|expr| &**expr),
);
} }
if self.settings.rules.enabled(Rule::UselessReturn) { if self.settings.rules.enabled(Rule::UselessReturn) {
pylint::rules::useless_return(self, stmt, body); pylint::rules::useless_return(
self,
stmt,
body,
returns.as_ref().map(|expr| &**expr),
);
} }
if self.settings.rules.enabled(Rule::ComplexStructure) { if self.settings.rules.enabled(Rule::ComplexStructure) {

View File

@ -6,9 +6,7 @@ use ruff_python_ast::visibility;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::docstrings::definition::{Definition, DefinitionKind}; use crate::docstrings::definition::{Definition, DefinitionKind};
pub(super) fn match_function_def( pub(super) fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, Option<&Expr>, &Vec<Stmt>) {
stmt: &Stmt,
) -> (&str, &Arguments, &Option<Box<Expr>>, &Vec<Stmt>) {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { StmtKind::FunctionDef {
name, name,
@ -23,7 +21,7 @@ pub(super) fn match_function_def(
returns, returns,
body, body,
.. ..
} => (name, args, returns, body), } => (name, args, returns.as_ref().map(|expr| &**expr), body),
_ => panic!("Found non-FunctionDef in match_name"), _ => panic!("Found non-FunctionDef in match_name"),
} }
} }

View File

@ -4,6 +4,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Stmt, StmtKind}
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation}; use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Fix}; use ruff_diagnostics::{Diagnostic, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::is_const_none;
use ruff_python_ast::helpers::{elif_else_range, end_of_statement}; use ruff_python_ast::helpers::{elif_else_range, end_of_statement};
use ruff_python_ast::types::Range; use ruff_python_ast::types::Range;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
@ -484,7 +485,7 @@ fn superfluous_else(checker: &mut Checker, stack: &Stack) -> bool {
} }
/// Run all checks from the `flake8-return` plugin. /// Run all checks from the `flake8-return` plugin.
pub fn function(checker: &mut Checker, body: &[Stmt]) { pub fn function(checker: &mut Checker, body: &[Stmt], returns: Option<&Expr>) {
// Skip empty functions. // Skip empty functions.
if body.is_empty() { if body.is_empty() {
return; return;
@ -535,7 +536,10 @@ pub fn function(checker: &mut Checker, body: &[Stmt]) {
if !result_exists(&stack.returns) { if !result_exists(&stack.returns) {
if checker.settings.rules.enabled(Rule::UnnecessaryReturnNone) { if checker.settings.rules.enabled(Rule::UnnecessaryReturnNone) {
unnecessary_return_none(checker, &stack); // Skip functions that have a return annotation that is not `None`.
if returns.map_or(true, is_const_none) {
unnecessary_return_none(checker, &stack);
}
} }
return; return;
} }

View File

@ -22,4 +22,24 @@ expression: diagnostics
row: 4 row: 4
column: 15 column: 15
parent: ~ parent: ~
- kind:
name: UnnecessaryReturnNone
body: "Do not explicitly `return None` in function if it is the only possible return value"
suggestion: "Remove explicit `return None`"
fixable: true
location:
row: 14
column: 8
end_location:
row: 14
column: 19
fix:
content: return
location:
row: 14
column: 8
end_location:
row: 14
column: 19
parent: ~

View File

@ -1,5 +1,5 @@
use log::error; use log::error;
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind}; use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic}; use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -46,7 +46,17 @@ impl AlwaysAutofixableViolation for UselessReturn {
} }
/// PLR1711 /// PLR1711
pub fn useless_return<'a>(checker: &mut Checker<'a>, stmt: &'a Stmt, body: &'a [Stmt]) { pub fn useless_return<'a>(
checker: &mut Checker<'a>,
stmt: &'a Stmt,
body: &'a [Stmt],
returns: Option<&'a Expr>,
) {
// Skip functions that have a return annotation that is not `None`.
if !returns.map_or(true, is_const_none) {
return;
}
// Skip empty functions. // Skip empty functions.
if body.is_empty() { if body.is_empty() {
return; return;

View File

@ -102,4 +102,24 @@ expression: diagnostics
row: 51 row: 51
column: 0 column: 0
parent: ~ parent: ~
- kind:
name: UselessReturn
body: "Useless `return` statement at end of function"
suggestion: "Remove useless `return` statement"
fixable: true
location:
row: 60
column: 8
end_location:
row: 60
column: 19
fix:
content: ""
location:
row: 60
column: 0
end_location:
row: 61
column: 0
parent: ~