Match the whole value in env2bool - #11082
Conversation
Fixes treeverse#11080 env2bool used re.search, so any value merely containing "1", "y", "yes" or "true" was truthy: DVC_EXP_AUTO_PUSH=my_path -> True (contains "y") DVC_EXP_AUTO_PUSH=v1.0 -> True (contains "1") DVC_EXP_AUTO_PUSH=nay -> True (contains "y") while "no" was correctly false, so the behaviour was also asymmetric in a confusing way. These are user-facing environment variables (DVC_EXP_AUTO_PUSH, DVC_SQLALCHEMY_ECHO, DVC_IGNORE_ISATTY, DVC_TEST), so the input really is arbitrary user text. Compare the whole value instead, after stripping and lowercasing. Every value that was intentionally supported still works; only substring matches stop being truthy.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #11082 +/- ##
==========================================
+ Coverage 90.68% 90.98% +0.30%
==========================================
Files 504 505 +1
Lines 39795 41146 +1351
Branches 3141 3263 +122
==========================================
+ Hits 36087 37436 +1349
- Misses 3042 3071 +29
+ Partials 666 639 -27 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
On the red The failing pre-commit hook is The same hook fails with the same error on Everything else in pre-commit passes on the changed files here — |
|
Note on the red
Everything else in the run, including |
Fixes #11080
env2booldecided truthiness with an unanchoredre.search, so any value that merely contained1,y,yesortruewas treated as true:It was also asymmetric in a way that's hard to reason about:
nois correctly false, butnayis true.This matters because these are user-facing environment variables where the input is arbitrary text —
DVC_EXP_AUTO_PUSH,DVC_SQLALCHEMY_ECHO,DVC_IGNORE_ISATTY,DVC_TEST. The likely way to hit it is a value meant to be negative that happens to contain a matching letter, or a non-boolean value put in one of these by mistake, which silently switches the feature on instead of being ignored.Change
Compare the whole value, after
strip()andlower(), against the set of accepted affirmatives.Every value that was intentionally supported still works (
1,y,yes,true, and case/whitespace variants); only substring matches stop being truthy. Theundefined=behaviour for an unset variable is unchanged.Note this is technically a behaviour change for anyone currently relying on a loose value being truthy — but since that path is indistinguishable from "user set something that isn't a boolean", tightening it seems clearly right. Happy to add a warning on unrecognised values instead if you'd prefer a softer landing.
Tests
test_env2boolis parametrised over the accepted affirmatives, the common negatives, and the five substring cases above;test_env2bool_undefinedpins the unset behaviour.Five of them fail on
main.