From a7a87be9929c21366c4a0bc2bed42f18f1e52f7b Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Thu, 26 Oct 2023 11:13:03 +0200 Subject: [PATCH] Fix SelectField choice backwards compatibility --- src/wtforms/fields/choices.py | 10 ++++++++-- src/wtforms/widgets/core.py | 16 +++++++++++++--- tests/conftest.py | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/wtforms/fields/choices.py b/src/wtforms/fields/choices.py index 4eb868969..a46db26ea 100644 --- a/src/wtforms/fields/choices.py +++ b/src/wtforms/fields/choices.py @@ -49,7 +49,13 @@ def __iter__(self): _form=None, _meta=self.meta, ) - for i, (value, label, checked, render_kw) in enumerate(self.iter_choices()): + for i, choice in enumerate(self.iter_choices()): + if len(choice) == 4: + value, label, checked, render_kw = choice + else: + value, label, checked = choice + render_kw = {} + opt = self._Option( label=label, id="%s-%d" % (self.id, i), **opts, **render_kw ) @@ -141,7 +147,7 @@ def pre_validate(self, form): if self.choices is None: raise TypeError(self.gettext("Choices cannot be None.")) - for _, _, match, _ in self.iter_choices(): + for _, _, match, *_ in self.iter_choices(): if match: break else: diff --git a/src/wtforms/widgets/core.py b/src/wtforms/widgets/core.py index b22f1c073..a4031d218 100644 --- a/src/wtforms/widgets/core.py +++ b/src/wtforms/widgets/core.py @@ -334,7 +334,7 @@ class Select: The field must provide an `iter_choices()` method which the widget will call on rendering; this method must yield tuples of - `(value, label, selected, render_kw)`. + `(value, label, selected)` or `(value, label, selected, render_kw)`. It also must provide a `has_groups()` method which tells whether choices are divided into groups, and if they do, the field must have an `iter_groups()` method that yields tuples of `(label, choices)`, where @@ -358,11 +358,21 @@ def __call__(self, field, **kwargs): if field.has_groups(): for group, choices in field.iter_groups(): html.append("" % html_params(label=group)) - for val, label, selected, render_kw in choices: + for choice in choices: + if len(choice) == 4: + val, label, selected, render_kw = choice + else: + val, label, selected = choice + render_kw = {} html.append(self.render_option(val, label, selected, **render_kw)) html.append("") else: - for val, label, selected, render_kw in field.iter_choices(): + for choice in field.iter_choices(): + if len(choice) == 4: + val, label, selected, render_kw = choice + else: + val, label, selected = choice + render_kw = {} html.append(self.render_option(val, label, selected, **render_kw)) html.append("") return Markup("".join(html)) diff --git a/tests/conftest.py b/tests/conftest.py index ec5081fcf..d3232348b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,7 +25,7 @@ def basic_widget_dummy_field(dummy_field_class): @pytest.fixture def select_dummy_field(dummy_field_class): - return dummy_field_class([("foo", "lfoo", True, {}), ("bar", "lbar", False, {})]) + return dummy_field_class([("foo", "lfoo", True), ("bar", "lbar", False)]) @pytest.fixture