🐛 fix(config): set_env override lost after load#3775
Merged
gaborbernat merged 2 commits intotox-dev:mainfrom Feb 19, 2026
Merged
🐛 fix(config): set_env override lost after load#3775gaborbernat merged 2 commits intotox-dev:mainfrom
gaborbernat merged 2 commits intotox-dev:mainfrom
Conversation
When `set_env` inherits via cross-section substitution and explicitly overrides the same key, `load()` moves the key from `_raw` to `_materialized` during iteration. By the time `_iter_needs_replacement` runs, the `key not in self._raw` guard no longer protects the explicit value, so the inherited one silently wins. Track originally-defined keys in a separate `_defined_keys` set that persists across `load()` calls, so deferred substitutions never overwrite values the user explicitly configured in the same section. Fixes tox-dev#3773
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When
set_envboth inherits via cross-section substitution (e.g.,{[testenv]set_env}) and explicitly overrides the same variable in the same section, the explicit value is silently replaced by the inherited one. 🐛 This regression was introduced in v4.39.0 and breaks a common configuration pattern where users layer environment variables across sections.The root cause is a timing issue in
_iter_needs_replacement(). During iteration,load()moves explicitly-set keys from_rawto_materialized. By the time the deferred cross-section substitution expands, thekey not in self._rawguard no longer sees those keys, so inherited values overwrite explicit ones. The fix tracks originally-defined keys in a separate_defined_keysset that persists acrossload()calls, ensuring deferred substitutions never overwrite values the user explicitly configured.All existing precedence behaviors are preserved: defaults still get overridden by cross-section values (#2872), explicit values still win over cross-section values (#2831), and
file|ordering still respects later inline definitions (#3335).Fixes #3773