Improve counting of message arguments when msg is provided as a keyword (#6456)

Closes https://github.com/astral-sh/ruff/issues/6454.
This commit is contained in:
Charlie Marsh 2023-08-09 16:39:10 -04:00 committed by GitHub
parent 3ecd263b4d
commit 395bb31247
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 14 deletions

View File

@ -19,6 +19,10 @@ logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
# do not handle keyword arguments # do not handle keyword arguments
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d") logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d")
logging.info(msg="Hello %s")
logging.info(msg="Hello %s %s")
import warning import warning
warning.warning("Hello %s %s", "World!") warning.warning("Hello %s %s", "World!")

View File

@ -15,6 +15,10 @@ logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
# do not handle keyword arguments # do not handle keyword arguments
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d", {"objects": 1, "modifications": 1, "errors": 1}) logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d", {"objects": 1, "modifications": 1, "errors": 1})
logging.info(msg="Hello")
logging.info(msg="Hello", something="else")
import warning import warning
warning.warning("Hello %s", "World!", "again") warning.warning("Hello %s", "World!", "again")

View File

@ -111,8 +111,8 @@ pub(crate) fn logging_call(checker: &mut Checker, call: &ast::ExprCall) {
let Some(Expr::Constant(ast::ExprConstant { let Some(Expr::Constant(ast::ExprConstant {
value: Constant::Str(value), value: Constant::Str(value),
.. ..
})) = call.arguments.find_argument("msg", 0) })) = call.arguments
else { .find_positional( 0) else {
return; return;
}; };

View File

@ -2126,23 +2126,21 @@ impl Arguments {
}) })
} }
/// Return the positional argument at the given index, or `None` if no such argument exists.
pub fn find_positional(&self, position: usize) -> Option<&Expr> {
self.args
.iter()
.take_while(|expr| !expr.is_starred_expr())
.nth(position)
}
/// Return the argument with the given name or at the given position, or `None` if no such /// Return the argument with the given name or at the given position, or `None` if no such
/// argument exists. Used to retrieve arguments that can be provided _either_ as keyword or /// argument exists. Used to retrieve arguments that can be provided _either_ as keyword or
/// positional arguments. /// positional arguments.
pub fn find_argument(&self, name: &str, position: usize) -> Option<&Expr> { pub fn find_argument(&self, name: &str, position: usize) -> Option<&Expr> {
self.keywords self.find_keyword(name)
.iter()
.find(|keyword| {
let Keyword { arg, .. } = keyword;
arg.as_ref().is_some_and(|arg| arg == name)
})
.map(|keyword| &keyword.value) .map(|keyword| &keyword.value)
.or_else(|| { .or_else(|| self.find_positional(position))
self.args
.iter()
.take_while(|expr| !expr.is_starred_expr())
.nth(position)
})
} }
} }