diff --git a/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py b/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py index 3e42d00521..3917322007 100644 --- a/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py +++ b/crates/ruff/resources/test/fixtures/pylint/logging_too_few_args.py @@ -10,6 +10,12 @@ logging.warning("Hello %s", "World!") # do not handle calls without any args logging.info("100% dynamic") +# do not handle calls with *args +logging.error("Example log %s, %s", "foo", "bar", "baz", *args) + +# do not handle calls with **kwargs +logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs) + import warning warning.warning("Hello %s %s", "World!") diff --git a/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py b/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py index 3127e97234..e03338fb23 100644 --- a/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py +++ b/crates/ruff/resources/test/fixtures/pylint/logging_too_many_args.py @@ -2,11 +2,16 @@ import logging logging.warning("Hello %s", "World!", "again") # [logging-too-many-args] -# do not handle calls with kwargs (like pylint) logging.warning("Hello %s", "World!", "again", something="else") logging.warning("Hello %s", "World!") +# do not handle calls with *args +logging.error("Example log %s, %s", "foo", "bar", "baz", *args) + +# do not handle calls with **kwargs +logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs) + import warning warning.warning("Hello %s", "World!", "again") diff --git a/crates/ruff/src/rules/pylint/rules/logging.rs b/crates/ruff/src/rules/pylint/rules/logging.rs index e187cab5c5..203da8fcc3 100644 --- a/crates/ruff/src/rules/pylint/rules/logging.rs +++ b/crates/ruff/src/rules/pylint/rules/logging.rs @@ -84,8 +84,22 @@ impl Violation for LoggingTooManyArgs { } } -/// Check logging calls for violations. +/// PLE1205 +/// PLE1206 pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { + // If there are any starred arguments, abort. + if args + .iter() + .any(|arg| matches!(arg.node, ExprKind::Starred { .. })) + { + return; + } + + // If there are any starred keyword arguments, abort. + if keywords.iter().any(|keyword| keyword.node.arg.is_none()) { + return; + } + if !is_logger_candidate(func) { return; } @@ -93,8 +107,6 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: if let ExprKind::Attribute { attr, .. } = &func.node { if LoggingLevel::from_str(attr.as_str()).is_some() { let call_args = SimpleCallArgs::new(args, keywords); - - // E1205 - E1206 if let Some(msg) = call_args.get_argument("msg", Some(0)) { if let ExprKind::Constant { value: Constant::Str(value), @@ -106,12 +118,6 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: return; } - if !call_args.kwargs.is_empty() { - // Keyword checking on logging strings is complicated by - // special keywords - out of scope. - return; - } - let message_args = call_args.args.len() - 1; if checker.settings.rules.enabled(&Rule::LoggingTooManyArgs) { @@ -124,7 +130,10 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: } if checker.settings.rules.enabled(&Rule::LoggingTooFewArgs) { - if message_args > 0 && summary.num_positional > message_args { + if message_args > 0 + && call_args.kwargs.is_empty() + && summary.num_positional > message_args + { checker.diagnostics.push(Diagnostic::new( LoggingTooFewArgs, Range::from_located(func), diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1205_logging_too_many_args.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1205_logging_too_many_args.py.snap index 7030b8b299..87c74fa545 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1205_logging_too_many_args.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE1205_logging_too_many_args.py.snap @@ -12,4 +12,14 @@ expression: diagnostics column: 15 fix: ~ parent: ~ +- kind: + LoggingTooManyArgs: ~ + location: + row: 5 + column: 0 + end_location: + row: 5 + column: 15 + fix: ~ + parent: ~