-
Notifications
You must be signed in to change notification settings - Fork 935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rule proposal: enforce strict boolean types in if statements #9148
Comments
Note though that PEP 8 recommends “For sequences, (strings, lists, tuples), use the fact that empty sequences are false”. |
Thanks for opening an issue! This feels contrary to the design of the Python language. I'm curious why you prefer this? Separately from whether or not it makes sense, I don't think we can actually do a good job implementing this until we have strong type inference. |
The motivation does make sense. Python makes it too tempting to abbreviate |
It would indeed require type inference, as in my case, I don't care what the value in the if statement is or where it comes from as long as it evaluates to a boolean. I would indeed expect to find these checks in As for the motivation, here is how I'd imagine finding this in the implicit-conditional (RUF-0XX)What it doesChecks whether non-boolean expressions are used in conditional statements. Why is it badAlthough it is allowed in Python, using non-booleans in conditional statements can have unintended consequences. For instance, a developer might intend to perform a null-check, but it might result in False if an integer equals 0, if a list or dictionary is empty, if a string is empty, etc. ExampleIn the following example, an empty list or a None will be treated the same, as def average(x: list[int] | None = None) -> float | None:
if x:
return None
return sum(x) / len(x) If we'd like an empty list or a None to be treated the same, use instead: def average(x: list[int] | None = None) -> float | None:
if x is None or len(x) == 0:
return None
return sum(x) / len(x) And if we don't, use instead: def average(x: list[int] | None = None) -> float | None:
if x is None:
return None
if len(x) == 0:
raise ValueError("List cannot be empty.")
return sum(x) / len(x) When not to use itIf you do not rely on optional types or if you want to keep your code short (i.e. in comprehensions), then, this rule might not be as useful to you. Similar scenarios may arise with:
|
A code guideline I enforce in my projects is only to use boolean values or expressions resulting in a boolean in an if statement. So far, I have not found a linter that enforces this automatically, hence my proposal to add this rule to
ruff
.In essence, I would like a lint rule that allows the following.
And disallows things like this
Don't know if this is something that
ruff
could implement. If this already exists in another linter, I'd be happy to hear it.The text was updated successfully, but these errors were encountered: