[pylint] Fix false positives and negatives with %b format character (PLE1300, PLE1307) - #27560
Conversation
…es detected (false negative)
Dropped 'n' value - seems some kind of stray value, there's no such formatting pattern. '%' also doesn't seem to have a chance to really appear as format char, Both were present from original implementation in PR 2572. Maybe `%` is some artifact of the cformat parser that was present back then.
No functional changes, just making bytes and ascii handling more explicit.
ntBre
left a comment
There was a problem hiding this comment.
Thanks, this makes sense to me. I just had one suggestion to simplify the changes a bit. My other two comments are mainly observations.
There was a problem hiding this comment.
I think the changes in this file are unnecessary because the rule already skips cases where CFormatString::from_str fails, which should now be the case for a string containing "%b".
There was a problem hiding this comment.
Makes sense, since from_str will be skipping %b, 'b' format character will never actually reach bad_string_format_type.
Though it's still confusing to see 'b' -> Integer here and misleading 'n', '%' chars and hardcoded characters in general, but I guess I can submit it as a refactor separately.
Reverted the changes in 966abd1
There was a problem hiding this comment.
Ah I see what you mean. I guess if I were starting from scratch, I would try to tie the successful parsing more directly to this narrower processing, like have FormatType::from also call CFormatString::from_str, or something like that. But it also doesn't feel like a high-priority refactor without resolving a bug, at least to me.
|
pylint] Fix false positive/negative with %b formatterpylint] Fix false positives and negatives with %b format character (PLE1300, PLE1307)
…er (`PLE1300`, `PLE1307`) (astral-sh#27560) ## Summary Noticed case below with possible false positive/negative when handling `%b` format character by rules https://docs.astral.sh/ruff/rules/bad-string-format-character/ and https://docs.astral.sh/ruff/rules/bad-string-format-type/ ```python # False negative: not flagged by bad-string-format-character # Runtime: ValueError: unsupported format character 'b' (0x62) at index 7 a = "hello %b" % 25 # False positive: bad-string-format-type # Runtime: ValueError: unsupported format character 'b' (0x62) at index 7 # It should report nothing, since the problem is not mismatching # formatter and provided value, but use of invalid format character in general. a = "hello %b" % "23" ``` This fix resolves both issues - first case is now reported and second results in no diagnostic. The root cause for was `bad-string-format-character` issue was `CFormatString` parser always parsing `%b` as `Bytes` type, while for bytes literals it's actually just an invalid character. Added `CFormatContext` enum, so parser can parse `%b` only when invoked from `CFormatBytes` and not from `CFormatString` and report issue when finds `%b` in string literals formatters. Second issue was caused by `bad-string-format-type` assuming `%b` is allowed only for integers, so it was reporting any other type as a mismatch. Now it just ignores `%b`, since it will be handled by `bad-string-format-character`. https://github.com/astral-sh/ruff/blob/17a00de2e298612201a8fe30790e9399204af1b9/crates/ruff_linter/src/rules/pylint/rules/bad_string_format_type.rs#L100 For completeness I also refactored `FormatType::from` in that rule to rely on `CFormatType` variants instead of hardcoding formatter characters It really just made it more clean without any functional changes: - `Ascii` is now handled explicitly as `Repr`, instead of assuming it's unknown - dropped non-existing formatters `n` and `%`, they are present from the original implementation astral-sh#2572 and are not valid formatters (possibly `%` is artifact from old cformat parser quirks). ## Test Plan Added tests for both rules, updated snapshots. All previous tests pass too.
Summary
Noticed case below with possible false positive/negative when handling
%bformat character by rules https://docs.astral.sh/ruff/rules/bad-string-format-character/ and https://docs.astral.sh/ruff/rules/bad-string-format-type/This fix resolves both issues - first case is now reported and second results in no diagnostic.
The root cause for was
bad-string-format-characterissue wasCFormatStringparser always parsing%basBytestype, while for bytes literals it's actually just an invalid character. AddedCFormatContextenum, so parser can parse%bonly when invoked fromCFormatBytesand not fromCFormatStringand report issue when finds%bin string literals formatters.Second issue was caused by
bad-string-format-typeassuming%bis allowed only for integers, so it was reporting any other type as a mismatch. Now it just ignores%b, since it will be handled bybad-string-format-character.ruff/crates/ruff_linter/src/rules/pylint/rules/bad_string_format_type.rs
Line 100 in 17a00de
For completeness I also refactored
FormatType::fromin that rule to rely onCFormatTypevariants instead of hardcoding formatter characters It really just made it more clean without any functional changes:Asciiis now handled explicitly asRepr, instead of assuming it's unknownnand%, they are present from the original implementation [pylint]: bad-string-format-type #2572 and are not valid formatters (possibly%is artifact from old cformat parser quirks).Test Plan
Added tests for both rules, updated snapshots. All previous tests pass too.