Skip to content

Warn when a string is passed as choices to OneOf - #3027

Open
ChrisJr404 wants to merge 1 commit into
marshmallow-code:devfrom
ChrisJr404:warn-oneof-string-choices
Open

Warn when a string is passed as choices to OneOf#3027
ChrisJr404 wants to merge 1 commit into
marshmallow-code:devfrom
ChrisJr404:warn-oneof-string-choices

Conversation

@ChrisJr404

Copy link
Copy Markdown

Closes #2074.

A string is a valid iterable, so it "works" as choices for OneOf — but it's almost always a mistake. The motivating case from the issue:

validate.OneOf("one", "two")   # oops: "one" is choices, "two" is labels

"one" in "one" is True, so the value "one" validates, and each character of the string is treated as a separate choice in the error text and in .options(). This is easy to hit and hard to spot.

This PR emits a UserWarning (at stacklevel=2, so it points at the caller) when a plain OneOf is constructed with a str for choices. Wrapping the string in a list silences it, as @deckar01 suggested on the issue:

validate.OneOf(list("abc"))   # no warning

ContainsOnly subclasses OneOf but legitimately accepts a string as a character set (that usage is covered by the existing test suite), so the warning is scoped to exact OneOf instances via type(self) is OneOf and ContainsOnly is unaffected. Behaviour is otherwise unchanged — string choices still validate exactly as before.

  • Added test_oneof_string_choices_warns covering the warning, the list-wrapping silence path, and that ContainsOnly does not warn.
  • Updated the existing string-based assertions in test_oneof to expect the warning.
  • Added a changelog entry and an AUTHORS.rst line.

A string is a valid iterable, so validate.OneOf("one", "two") silently
treats "one" as the choices and "two" as the labels, and each character
becomes a separate choice. Emit a warning to flag this likely mistake;
wrapping the string in a list silences it. ContainsOnly deliberately
accepts strings, so only plain OneOf instances warn.

Closes marshmallow-code#2074
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.

Emit warning when user passes string instead of list to OneOf

1 participant