Fix cast_to_bool to treat whitespace-only strings as False#2462
Fix cast_to_bool to treat whitespace-only strings as False#2462developreiloyo wants to merge 4 commits intocopier-org:masterfrom
Conversation
sisp
left a comment
There was a problem hiding this comment.
Thanks for your contribution around bool casting improvements, @developreiloyo! 🙇 I've left a few inline comments.
copier/_tools.py
Outdated
| # Treat whitespace-only string as False | ||
| if isinstance(value,str) and not value.strip(): |
There was a problem hiding this comment.
| # Treat whitespace-only string as False | |
| if isinstance(value,str) and not value.strip(): | |
| # Treat whitespace-only string as False | |
| if isinstance(value, str) and not value.strip(): |
| with suppress(AttributeError): | ||
| lower = value.lower() | ||
| if lower in {"y", "yes", "t", "true", "on"}: | ||
| return True | ||
| elif lower in {"n", "no", "f", "false", "off", "~", "null", "none"}: | ||
| return False |
There was a problem hiding this comment.
Would it make sense to avoid the special case handling for whitespace-only strings and extend the string handling instead?
with suppress(AttributeError):
- lower = value.lower()
+ lower = value.lower().strip()
if lower in {"y", "yes", "t", "true", "on"}:
return True
- elif lower in {"n", "no", "f", "false", "off", "~", "null", "none"}:
+ elif lower in {"n", "no", "f", "false", "off", "~", "null", "none", ""}:
return FalseThere was a problem hiding this comment.
Thanks, @sisp! I included "" because without it, whitespace-only strings like " " fall through to bool(value), which returns True. Since .strip() normalizes them to "", treating it as a falsy keyword feels like the cleanest fix.
There was a problem hiding this comment.
Isn't this the same as
lower = value.lower().strip()
if ...:
...
elif lower in {..., ""}:
return Falsebut without a special case? " " would be captured by the elif branch.
There was a problem hiding this comment.
Thanks for the suggestion I realized the redundant check wasn’t needed, so I updated the implementation to use:
if isinstance(value, str) and not value.strip():
return False
There was a problem hiding this comment.
Ah, this is not what I meant. When we're at
Lines 130 to 136 in cd45f37
then the value is likely a string with methods like .lower() and also .strip(). So, I was thinking we only need to also strip leading and trailing whitespaces via .strip() and add the empty string to the set of values that shall cast to False. For this, I believe we don't need the special-case handling
if isinstance(value, str) and not value.strip():
return Falsebut instead can extend the string handling logic just a little bit.
- Normalize string input with .strip() before keyword matching
- Include empty string ('') in false keyword list to handle normalized whitespace
- Extend existing test to cover both whitespace-only and padded valid keywords
- Add explicit check: if isinstance(value, str) and not value.strip(): return False - Remove "" from false keyword list - Avoid fallback to bool(value) for whitespace-only strings
|
|
||
| # Handle whitespace-only strings first | ||
| if isinstance(value, str) and not value.strip(): | ||
| return False | ||
|
|
There was a problem hiding this comment.
See #2462 (comment):
| # Handle whitespace-only strings first | |
| if isinstance(value, str) and not value.strip(): | |
| return False |
What does this change?
cast_to_boolwas treating whitespace-only strings (e.g." ","\n") asTruedue to Python’s defaultbool(str)behavior.This PR adds an explicit check to treat empty and whitespace-only strings as
False.What was done?
Falsefor whitespace-only strings.Why this approach?
The change is minimal and does not alter existing behavior for numbers, YAML booleans, or standard truthy values.