Skip to content

Commit 0bf7f8b

Browse files
Merge pull request #2551 from pallets-eco/fix/wtforms-3.2
Add compatibility for wtforms 3.2+
2 parents 9552b27 + c0c63b4 commit 0bf7f8b

File tree

5 files changed

+41
-8
lines changed

5 files changed

+41
-8
lines changed

doc/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Changelog
66

77
Fixes:
88

9+
* Fixes compatibility with WTForms 3.2+.
910
* The `Apply` button for filters will show/hide correctly again
1011
* Fix `translations_path` attribute when Flask-Admin is used with Flask-Babel
1112
* Some translation updates.

flask_admin/_compat.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,19 @@ def as_unicode(s):
3939
def csv_encode(s):
4040
"""Returns unicode string expected by Python 3's csv module"""
4141
return as_unicode(s)
42+
43+
44+
def _iter_choices_wtforms_compat(val, label, selected):
45+
"""Compatibility for 3-tuples and 4-tuples in iter_choices
46+
47+
https://wtforms.readthedocs.io/en/3.2.x/changes/#version-3-2-0
48+
"""
49+
from packaging.version import Version
50+
import wtforms
51+
52+
wtforms_version = Version(wtforms.__version__)
53+
54+
if wtforms_version >= Version("3.2.0"):
55+
return val, label, selected, {}
56+
57+
return val, label, selected

flask_admin/contrib/sqla/fields.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from wtforms.utils import unset_value
1111
from wtforms.validators import ValidationError
1212

13+
from flask_admin._compat import _iter_choices_wtforms_compat
1314
from flask_admin._compat import iteritems
1415
from flask_admin._compat import string_types
1516
from flask_admin._compat import text_type
@@ -111,10 +112,14 @@ def _get_object_list(self):
111112

112113
def iter_choices(self):
113114
if self.allow_blank:
114-
yield ("__None", self.blank_text, self.data is None)
115+
yield _iter_choices_wtforms_compat(
116+
"__None", self.blank_text, self.data is None
117+
)
115118

116119
for pk, obj in self._get_object_list():
117-
yield (pk, self.get_label(obj), obj == self.data)
120+
yield _iter_choices_wtforms_compat(
121+
pk, self.get_label(obj), obj == self.data
122+
)
118123

119124
def process_formdata(self, valuelist):
120125
if valuelist:
@@ -174,7 +179,9 @@ def _set_data(self, data):
174179

175180
def iter_choices(self):
176181
for pk, obj in self._get_object_list():
177-
yield (pk, self.get_label(obj), obj in self.data)
182+
yield _iter_choices_wtforms_compat(
183+
pk, self.get_label(obj), obj in self.data
184+
)
178185

179186
def process_formdata(self, valuelist):
180187
self._formdata = set(valuelist)

flask_admin/form/fields.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from wtforms import fields
77

8+
from flask_admin._compat import _iter_choices_wtforms_compat
89
from flask_admin._compat import as_unicode
910
from flask_admin._compat import text_type
1011
from flask_admin.babel import gettext
@@ -146,13 +147,17 @@ def __init__(
146147

147148
def iter_choices(self):
148149
if self.allow_blank:
149-
yield ("__None", self.blank_text, self.data is None)
150+
yield _iter_choices_wtforms_compat(
151+
"__None", self.blank_text, self.data is None
152+
)
150153

151154
for choice in self.choices:
152155
if isinstance(choice, tuple):
153-
yield (choice[0], choice[1], self.coerce(choice[0]) == self.data)
156+
yield _iter_choices_wtforms_compat(
157+
choice[0], choice[1], self.coerce(choice[0]) == self.data
158+
)
154159
else:
155-
yield (
160+
yield _iter_choices_wtforms_compat(
156161
choice.value,
157162
choice.name,
158163
self.coerce(choice.value) == self.data,

tox.ini

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ deps =
2525
-r requirements/tests.txt
2626
commands_pre =
2727
noflaskbabel: pip uninstall -y flask-babel
28-
commands = pytest -v --tb=short --basetemp={envtmpdir} flask_admin/tests {posargs}
28+
commands =
29+
pip freeze
30+
pytest -v --tb=short --basetemp={envtmpdir} flask_admin/tests {posargs}
2931

3032
[testenv:py38-min]
3133
deps = -r requirements-skip/tests-min.txt
32-
commands = pytest -v --tb=short --basetemp={envtmpdir} flask_admin/tests -W 'default::DeprecationWarning' {posargs}
34+
commands =
35+
pip freeze
36+
pytest -v --tb=short --basetemp={envtmpdir} flask_admin/tests -W 'default::DeprecationWarning' {posargs}
3337

3438
[testenv:style]
3539
deps = pre-commit

0 commit comments

Comments
 (0)