Skip to content

Conversation

@IDrokin117
Copy link
Contributor

@IDrokin117 IDrokin117 commented Oct 27, 2025

Summary

Closes #21048

Fix some false positive edge cases when determining string truthiness. The following cases are now treated as unknown truthiness:

  1. Comparison expressions can return any value, even empty strings.
  2. F-strings with format specs can produce either empty or non-empty strings:
bool(f"{'mystring':.0}") # Returns False

Additionally, fixed a bug that caused f"{f""!s}" to be treated as non-empty. Since .iter().all() returns true if the iterator is empty, f-strings with no elements (like nested f"{f""!s}") were incorrectly treated as non-empty.

Test Plan

  • Added test cases to S604 since Truthiness has no tests of its own

@github-actions
Copy link
Contributor

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks good, I just had a couple of small ideas/suggestions.

}
})
!f_string.elements.is_empty()
&& f_string.elements.iter().all(|element| match element {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this just be any instead? I could certainly be wrong, but it seems like we should check if any part is non-empty rather than all parts are non-empty. That would also give the correct behavior for the empty iterator and match the outer any on line 1401.

I tried this locally, and I think it fixed an existing bug in a SIM222 test too.

Comment on lines +1360 to +1362
// Compare can return any value, even empty string
// https://docs.python.org/3/reference/datamodel.html#object.__ge__
Expr::Compare(_) => false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this down to the other complex expressions below? It seems slightly out of place in this block now that the other variants are all true.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more precise, this could still be true if all the operators in the Compare are the ones guaranteed to return bools (in, is, is not, and not in).

@ntBre ntBre added the bug Something isn't working label Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

is_non_empty_f_string has false positives

3 participants