Skip to content

Fix OneOf.options() emitting phantom entries when labels outnumber choices#2909

Merged
sloria merged 4 commits intomarshmallow-code:devfrom
rstar327:fix-oneof-options-phantom
Mar 25, 2026
Merged

Fix OneOf.options() emitting phantom entries when labels outnumber choices#2909
sloria merged 4 commits intomarshmallow-code:devfrom
rstar327:fix-oneof-options-phantom

Conversation

@rstar327
Copy link
Copy Markdown
Contributor

Fixes #2869

OneOf.options() used zip_longest(choices, labels, fillvalue="") which produced phantom ('', 'label') entries when labels was longer than choices. These phantom entries have no corresponding choice and are misleading.

This PR replaces zip_longest with explicit padding/truncation so that options() always returns exactly as many pairs as there are choices:

  • Extra labels beyond the number of choices are silently ignored
  • Missing labels are padded with empty strings (preserving existing behavior)
# Before
OneOf(choices=[], labels=["extra"]).options()  # [('', 'extra')]

# After
OneOf(choices=[], labels=["extra"]).options()  # []

All 1132 tests pass.

Copy link
Copy Markdown
Member

@lafrech lafrech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks.

@lafrech
Copy link
Copy Markdown
Member

lafrech commented Mar 13, 2026

Once this is merged, there will be only one call of zip_longest left, in _invoke_processors.

While removing it breaks a test, I find the use case questionable and I'd be tempted to suggest removing it in next major as allowing processors to modify the length of collections opens the door to unpredictable issues.

@sloria sloria enabled auto-merge (squash) March 25, 2026 22:18
@sloria sloria merged commit 65374df into marshmallow-code:dev Mar 25, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OneOf.options() emits extra pairs when labels outnumber choices

3 participants