Skip to content

fix: cross-section substitution resolves to empty when no factors match#3810

Merged
gaborbernat merged 7 commits intotox-dev:mainfrom
worksbyfriday:fix-cross-section-factor-3809
Feb 23, 2026
Merged

fix: cross-section substitution resolves to empty when no factors match#3810
gaborbernat merged 7 commits intotox-dev:mainfrom
worksbyfriday:fix-cross-section-factor-3809

Conversation

@worksbyfriday
Copy link
Contributor

Summary

Fixes #3809

Cross-section substitution {[section]key} now correctly resolves to empty string when the referenced value contains only factor-conditional lines and no factors match the requesting environment.

Before: {[devpisettings]storagebackend} remained as a literal unresolved reference when no factors matched.

After: Resolves to empty string, matching pre-4.39.0 behavior.

Root cause

PR #3751 (fixing #3189) added a KeyError in process_raw() when factor filtering empties a value that originally had content. This correctly causes same-section config values (like base_python) to fall through to their computed defaults. However, for cross-section references loaded via SectionProxy, the KeyError propagated to the replacer which returned None (unresolved), leaving the literal {[section]key} in output.

Fix

In ReplaceReferenceIni.__call__(), when a SectionProxy lookup raises KeyError but the key exists in the section, return empty string instead of propagating the error. This preserves the #3189 fix while correctly handling cross-section references.

Test plan

🤖 Generated with Claude Code

When {[section]key} references a value with factor-conditional lines and
no factors match, the substitution should resolve to empty string rather
than remaining unresolved as a literal reference.

The root cause: process_raw() raises KeyError when factor filtering empties
a value that originally had content (added in tox-dev#3751 to fix tox-dev#3189). For
same-section config values this is correct — it allows fallback to computed
defaults (e.g. base_python derived from env name). But for cross-section
references via SectionProxy, the KeyError propagated all the way up to
the replacer, which returned None (unresolved), leaving the literal
{[section]key} in the output.

The fix: when a SectionProxy lookup raises KeyError but the key exists in
the section, the factor filtering emptied the value — return empty string
instead of propagating the error. This preserves the tox-dev#3189 fix for
same-section config values while correctly handling cross-section references.

Fixes tox-dev#3809

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
worksbyfriday and others added 2 commits February 22, 2026 09:37
Move SectionProxy resolution logic into a helper method to stay
within ruff's branch count and nesting depth limits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gaborbernat gaborbernat enabled auto-merge (squash) February 23, 2026 12:53
Consistent with the multiline style requested in review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
auto-merge was automatically disabled February 23, 2026 14:51

Head branch was pushed to by a user without write access

@gaborbernat gaborbernat merged commit 9adb727 into tox-dev:main Feb 23, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cross-section substitution fails since 4.39.0 when there should be an empty string

2 participants