WTForms 3.2.1__tar.gz → 3.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. {wtforms-3.2.1 → wtforms-3.3.0}/.gitignore +1 -0
  2. {wtforms-3.2.1 → wtforms-3.3.0}/CHANGES.rst +120 -1
  3. {wtforms-3.2.1 → wtforms-3.3.0}/PKG-INFO +5 -12
  4. {wtforms-3.2.1 → wtforms-3.3.0}/README.rst +0 -7
  5. {wtforms-3.2.1 → wtforms-3.3.0}/docs/conf.py +15 -0
  6. {wtforms-3.2.1 → wtforms-3.3.0}/docs/crash_course.rst +16 -0
  7. {wtforms-3.2.1 → wtforms-3.3.0}/docs/faq.rst +1 -1
  8. {wtforms-3.2.1 → wtforms-3.3.0}/docs/fields.rst +260 -40
  9. {wtforms-3.2.1 → wtforms-3.3.0}/docs/forms.rst +5 -3
  10. {wtforms-3.2.1 → wtforms-3.3.0}/docs/specific_problems.rst +5 -5
  11. {wtforms-3.2.1 → wtforms-3.3.0}/docs/validators.rst +7 -4
  12. {wtforms-3.2.1 → wtforms-3.3.0}/docs/whats_new.rst +16 -1
  13. wtforms-3.3.0/docs/widgets.rst +161 -0
  14. {wtforms-3.2.1 → wtforms-3.3.0}/pyproject.toml +67 -4
  15. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/__init__.py +13 -1
  16. wtforms-3.3.0/src/wtforms/_compat.py +15 -0
  17. wtforms-3.3.0/src/wtforms/datalist.py +136 -0
  18. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/__init__.py +10 -0
  19. wtforms-3.3.0/src/wtforms/fields/choices.py +625 -0
  20. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/core.py +46 -5
  21. wtforms-3.3.0/src/wtforms/fields/datetime.py +290 -0
  22. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/form.py +18 -4
  23. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/list.py +102 -19
  24. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/numeric.py +40 -16
  25. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/fields/simple.py +68 -16
  26. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/form.py +40 -1
  27. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/README.md +12 -1
  28. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ar/LC_MESSAGES/wtforms.mo +0 -0
  29. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ar/LC_MESSAGES/wtforms.po +8 -8
  30. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/bg/LC_MESSAGES/wtforms.mo +0 -0
  31. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/bg/LC_MESSAGES/wtforms.po +7 -7
  32. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ca/LC_MESSAGES/wtforms.mo +0 -0
  33. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ca/LC_MESSAGES/wtforms.po +8 -9
  34. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.mo +0 -0
  35. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.po +7 -7
  36. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/cy/LC_MESSAGES/wtforms.mo +0 -0
  37. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/cy/LC_MESSAGES/wtforms.po +9 -8
  38. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/de/LC_MESSAGES/wtforms.mo +0 -0
  39. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/de/LC_MESSAGES/wtforms.po +7 -7
  40. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/de_CH/LC_MESSAGES/wtforms.mo +0 -0
  41. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/de_CH/LC_MESSAGES/wtforms.po +7 -7
  42. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/el/LC_MESSAGES/wtforms.mo +0 -0
  43. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/el/LC_MESSAGES/wtforms.po +7 -7
  44. wtforms-3.3.0/src/wtforms/locale/en/LC_MESSAGES/wtforms.mo +0 -0
  45. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/en/LC_MESSAGES/wtforms.po +59 -43
  46. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/es/LC_MESSAGES/wtforms.mo +0 -0
  47. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/es/LC_MESSAGES/wtforms.po +5 -6
  48. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/et/LC_MESSAGES/wtforms.mo +0 -0
  49. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/et/LC_MESSAGES/wtforms.po +7 -7
  50. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fa/LC_MESSAGES/wtforms.mo +0 -0
  51. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fa/LC_MESSAGES/wtforms.po +6 -6
  52. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fi/LC_MESSAGES/wtforms.mo +0 -0
  53. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fi/LC_MESSAGES/wtforms.po +7 -7
  54. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fr/LC_MESSAGES/wtforms.mo +0 -0
  55. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/fr/LC_MESSAGES/wtforms.po +8 -9
  56. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/he/LC_MESSAGES/wtforms.mo +0 -0
  57. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/he/LC_MESSAGES/wtforms.po +7 -7
  58. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/hu/LC_MESSAGES/wtforms.mo +0 -0
  59. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/hu/LC_MESSAGES/wtforms.po +7 -7
  60. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/it/LC_MESSAGES/wtforms.mo +0 -0
  61. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/it/LC_MESSAGES/wtforms.po +10 -10
  62. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ja/LC_MESSAGES/wtforms.mo +0 -0
  63. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ja/LC_MESSAGES/wtforms.po +7 -7
  64. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/kk/LC_MESSAGES/wtforms.mo +0 -0
  65. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/kk/LC_MESSAGES/wtforms.po +7 -8
  66. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ko/LC_MESSAGES/wtforms.mo +0 -0
  67. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ko/LC_MESSAGES/wtforms.po +5 -6
  68. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/nb/LC_MESSAGES/wtforms.mo +0 -0
  69. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/nb/LC_MESSAGES/wtforms.po +7 -7
  70. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/nl/LC_MESSAGES/wtforms.mo +0 -0
  71. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/nl/LC_MESSAGES/wtforms.po +9 -11
  72. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/pl/LC_MESSAGES/wtforms.mo +0 -0
  73. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/pl/LC_MESSAGES/wtforms.po +9 -10
  74. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/pt/LC_MESSAGES/wtforms.mo +0 -0
  75. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/pt/LC_MESSAGES/wtforms.po +5 -6
  76. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ro/LC_MESSAGES/wtforms.mo +0 -0
  77. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ro/LC_MESSAGES/wtforms.po +11 -11
  78. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ru/LC_MESSAGES/wtforms.mo +0 -0
  79. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/ru/LC_MESSAGES/wtforms.po +8 -9
  80. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/sk/LC_MESSAGES/wtforms.mo +0 -0
  81. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/sk/LC_MESSAGES/wtforms.po +5 -6
  82. wtforms-3.3.0/src/wtforms/locale/sr/LC_MESSAGES/wtforms.mo +0 -0
  83. wtforms-3.3.0/src/wtforms/locale/sr/LC_MESSAGES/wtforms.po +189 -0
  84. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/sv/LC_MESSAGES/wtforms.mo +0 -0
  85. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/sv/LC_MESSAGES/wtforms.po +5 -6
  86. wtforms-3.3.0/src/wtforms/locale/ta/LC_MESSAGES/wtforms.mo +0 -0
  87. wtforms-3.3.0/src/wtforms/locale/ta/LC_MESSAGES/wtforms.po +186 -0
  88. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/tr/LC_MESSAGES/wtforms.mo +0 -0
  89. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/tr/LC_MESSAGES/wtforms.po +5 -6
  90. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/uk/LC_MESSAGES/wtforms.mo +0 -0
  91. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/uk/LC_MESSAGES/wtforms.po +6 -7
  92. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/wtforms.pot +54 -39
  93. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/zh/LC_MESSAGES/wtforms.mo +0 -0
  94. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/zh/LC_MESSAGES/wtforms.po +7 -7
  95. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/zh_TW/LC_MESSAGES/wtforms.mo +0 -0
  96. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/locale/zh_TW/LC_MESSAGES/wtforms.po +5 -6
  97. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/validators.py +227 -34
  98. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/widgets/__init__.py +4 -0
  99. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/widgets/core.py +185 -79
  100. {wtforms-3.2.1 → wtforms-3.3.0}/tests/common.py +1 -1
  101. {wtforms-3.2.1 → wtforms-3.3.0}/tests/conftest.py +18 -4
  102. wtforms-3.3.0/tests/fields/test_button.py +88 -0
  103. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_date.py +22 -0
  104. wtforms-3.3.0/tests/fields/test_datetime.py +129 -0
  105. wtforms-3.3.0/tests/fields/test_datetimelocal.py +141 -0
  106. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_decimal.py +17 -0
  107. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_field.py +9 -0
  108. wtforms-3.3.0/tests/fields/test_float.py +54 -0
  109. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_form.py +99 -0
  110. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_html5.py +62 -9
  111. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_integer.py +22 -0
  112. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_label.py +2 -4
  113. wtforms-3.3.0/tests/fields/test_list.py +488 -0
  114. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_radio.py +35 -6
  115. wtforms-3.3.0/tests/fields/test_select.py +950 -0
  116. wtforms-3.3.0/tests/fields/test_selectmultiple.py +371 -0
  117. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_time.py +22 -0
  118. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_week.py +22 -0
  119. wtforms-3.3.0/tests/test_datalist.py +439 -0
  120. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_form.py +22 -0
  121. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_locale_babel.py +3 -3
  122. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_widgets.py +141 -5
  123. wtforms-3.3.0/tests/validators/test_date_range.py +126 -0
  124. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_disabled.py +3 -0
  125. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_email.py +47 -0
  126. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_number_range.py +19 -0
  127. wtforms-3.3.0/tests/validators/test_regexp.py +106 -0
  128. wtforms-3.3.0/tests/validators/test_url.py +143 -0
  129. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_uuid.py +16 -1
  130. wtforms-3.2.1/docs/requirements.txt +0 -5
  131. wtforms-3.2.1/docs/widgets.rst +0 -104
  132. wtforms-3.2.1/src/wtforms/fields/choices.py +0 -229
  133. wtforms-3.2.1/src/wtforms/fields/datetime.py +0 -170
  134. wtforms-3.2.1/src/wtforms/locale/en/LC_MESSAGES/wtforms.mo +0 -0
  135. wtforms-3.2.1/tests/fields/test_datetime.py +0 -72
  136. wtforms-3.2.1/tests/fields/test_datetimelocal.py +0 -74
  137. wtforms-3.2.1/tests/fields/test_float.py +0 -30
  138. wtforms-3.2.1/tests/fields/test_list.py +0 -249
  139. wtforms-3.2.1/tests/fields/test_select.py +0 -285
  140. wtforms-3.2.1/tests/fields/test_selectmultiple.py +0 -207
  141. wtforms-3.2.1/tests/validators/test_regexp.py +0 -64
  142. wtforms-3.2.1/tests/validators/test_url.py +0 -76
  143. wtforms-3.2.1/tox.ini +0 -37
  144. {wtforms-3.2.1 → wtforms-3.3.0}/LICENSE.rst +0 -0
  145. {wtforms-3.2.1 → wtforms-3.3.0}/docs/Makefile +0 -0
  146. {wtforms-3.2.1 → wtforms-3.3.0}/docs/_static/logo_joined.svg +0 -0
  147. {wtforms-3.2.1 → wtforms-3.3.0}/docs/_static/logo_split.svg +0 -0
  148. {wtforms-3.2.1 → wtforms-3.3.0}/docs/_static/logo_square.svg +0 -0
  149. {wtforms-3.2.1 → wtforms-3.3.0}/docs/changes.rst +0 -0
  150. {wtforms-3.2.1 → wtforms-3.3.0}/docs/contributing.rst +0 -0
  151. {wtforms-3.2.1 → wtforms-3.3.0}/docs/csrf.rst +0 -0
  152. {wtforms-3.2.1 → wtforms-3.3.0}/docs/ext.rst +0 -0
  153. {wtforms-3.2.1 → wtforms-3.3.0}/docs/i18n.rst +0 -0
  154. {wtforms-3.2.1 → wtforms-3.3.0}/docs/index.rst +0 -0
  155. {wtforms-3.2.1 → wtforms-3.3.0}/docs/license.rst +0 -0
  156. {wtforms-3.2.1 → wtforms-3.3.0}/docs/make.bat +0 -0
  157. {wtforms-3.2.1 → wtforms-3.3.0}/docs/meta.rst +0 -0
  158. {wtforms-3.2.1 → wtforms-3.3.0}/hatch_build.py +0 -0
  159. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/csrf/__init__.py +0 -0
  160. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/csrf/core.py +0 -0
  161. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/csrf/session.py +0 -0
  162. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/i18n.py +0 -0
  163. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/meta.py +0 -0
  164. {wtforms-3.2.1 → wtforms-3.3.0}/src/wtforms/utils.py +0 -0
  165. {wtforms-3.2.1 → wtforms-3.3.0}/tests/__init__.py +0 -0
  166. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/__init__.py +0 -0
  167. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_boolean.py +0 -0
  168. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_color.py +0 -0
  169. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_custom.py +0 -0
  170. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_defaults.py +0 -0
  171. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_file.py +0 -0
  172. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_filters.py +0 -0
  173. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_flags.py +0 -0
  174. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_hidden.py +0 -0
  175. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_month.py +0 -0
  176. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_password.py +0 -0
  177. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_string.py +0 -0
  178. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_submit.py +0 -0
  179. {wtforms-3.2.1 → wtforms-3.3.0}/tests/fields/test_textarea.py +0 -0
  180. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_csrf.py +0 -0
  181. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_i18n.py +0 -0
  182. {wtforms-3.2.1 → wtforms-3.3.0}/tests/test_webob.py +0 -0
  183. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/__init__.py +0 -0
  184. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_anyof.py +0 -0
  185. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_data_required.py +0 -0
  186. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_equal_to.py +0 -0
  187. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_input_required.py +0 -0
  188. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_ipaddress.py +0 -0
  189. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_lazy_proxy.py +0 -0
  190. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_length.py +0 -0
  191. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_mac_address.py +0 -0
  192. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_noneof.py +0 -0
  193. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_optional.py +0 -0
  194. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_readonly.py +0 -0
  195. {wtforms-3.2.1 → wtforms-3.3.0}/tests/validators/test_validators.py +0 -0
@@ -15,3 +15,4 @@ __pycache__/
15
15
  /htmlcov/
16
16
  /docs/_build/
17
17
  /src/wtforms/locale/**/wtforms.mo
18
+ uv.lock
@@ -1,5 +1,125 @@
1
1
  .. currentmodule:: wtforms
2
2
 
3
+ Version 3.3.0
4
+ -------------
5
+
6
+ Released 2026-10-23
7
+
8
+ - Drop support for Python 3.10. Add support for Python 3.15.
9
+ - Add native :class:`DataList` support. Options are declared with
10
+ :class:`DataListChoice`, or with the shorthand ``{value: label}``
11
+ dict syntax. :issue:`653` :issue:`886` :pr:`921`
12
+ - Add :class:`~fields.ButtonField` to render ``<button type="submit">``
13
+ controls with string values. :issue:`784` :pr:`892`
14
+ - Add :class:`~validators.DateRange`. ``min`` and ``max`` may be callables
15
+ to compute dynamic bounds; :class:`~validators.NumberRange` accepts
16
+ callables on the same terms. :pr:`787`
17
+ - Add :class:`~fields.FieldList` ``insert_entry`` and indexed ``pop_entry``.
18
+ The following entries are renumbered, with their ids and labels.
19
+ :issue:`256` :pr:`901` :pr:`912`
20
+ - :class:`~fields.SelectField` refactor. Options are declared with
21
+ :class:`~fields.SelectChoice`, which takes HTML attributes in
22
+ ``render_kw`` and an ``optgroup``. ``iter_choices``
23
+ and ``iter_groups`` yield
24
+ :class:`~fields.Choice` objects. ``choices`` also accepts the shorthand
25
+ dict syntax: ``{value: label}`` for flat options and
26
+ ``{label: {value: label}}`` for optgroups. :issue:`692` :issue:`886`
27
+ :issue:`922` :pr:`739` :pr:`889`
28
+ - ``choices`` callables on :class:`~fields.SelectField` and
29
+ :class:`DataList` may accept ``(form, field)``. They run on the
30
+ first read and their result is cached. Calling
31
+ :meth:`~form.BaseForm.post_process` again refreshes them, also for the
32
+ entries added with :meth:`~fields.FieldList.append_entry` and
33
+ :meth:`~fields.FieldList.insert_entry`. :issue:`922`
34
+ - Add :func:`fields.enum_choices`, :func:`fields.enum_coerce` and
35
+ :func:`~datalist.enum_datalist` for Enum-backed choices. :issue:`338`
36
+ :issue:`922` :pr:`916`
37
+ - Add :meth:`fields.Field.post_process` and
38
+ :meth:`form.BaseForm.post_process` hooks, propagated through
39
+ :class:`~fields.FormField` and :class:`~fields.FieldList`, for
40
+ cross-field finalization. :issue:`922`
41
+ - Add ``Field._form`` and ``BaseForm._parent_form`` so fields and nested
42
+ forms can reach their enclosing form. :class:`~fields.FieldList` entries
43
+ and :class:`~fields.SelectField` option subfields no longer get
44
+ ``form=None``. :issue:`922`
45
+ - Add ``invalid_value_message`` and ``invalid_choice_message`` keyword
46
+ arguments for customizing built-in field error messages. On
47
+ :class:`~fields.SelectMultipleField`, ``invalid_choice_message`` may also
48
+ be a callable for custom pluralization. :issue:`39` :issue:`832` :pr:`902`
49
+ - :class:`~fields.SelectField` and :class:`~fields.SelectMultipleField`
50
+ ``pre_validate`` short-circuits when ``process_formdata`` already produced
51
+ an error, so a single coercion failure no longer surfaces as both an
52
+ "invalid value" and an "invalid choice" error. :pr:`902`
53
+ - Numeric, date, time and select fields report a validation error instead of
54
+ raising a :class:`TypeError` when the input is not a string. :pr:`936`
55
+ - Each bound field gets its own copy of ``render_kw``, and so does its
56
+ :class:`DataList`. Changing one of them on a form instance no
57
+ longer changes it on the other ones. :issue:`942`
58
+ - Make :class:`~fields.FloatField` render as ``<input type="number">`` with
59
+ ``step="any"``. :issue:`677` :pr:`679`
60
+ - Add a ``tz`` parameter to :class:`~fields.DateTimeLocalField` to associate a
61
+ timezone with the input. :issue:`833` :pr:`905`
62
+ - Let :class:`~widgets.RangeInput` accept ``min`` and ``max`` at construction
63
+ time. :issue:`693` :pr:`898`
64
+ - ``FieldList._add_entry`` routes through
65
+ :meth:`~meta.DefaultMeta.bind_field`, like the top-level fields. Custom
66
+ ``Meta.bind_field`` overrides were silently bypassed for
67
+ :class:`~fields.FieldList` entries. :pr:`891`
68
+ - Reset :class:`~fields.FieldList` index state when reprocessing entries.
69
+ :issue:`874` :pr:`895`
70
+ - Do not render a ``for`` attribute on the main label of
71
+ :class:`~fields.RadioField`. :issue:`775` :pr:`900`
72
+ - Render ``False`` as ``value="False"`` in :class:`~fields.SelectField`
73
+ options instead of omitting the attribute. :issue:`878` :pr:`908`
74
+ - Let render-time ``checked`` kwargs take precedence over the field's value
75
+ in :class:`~widgets.CheckboxInput` and :class:`~widgets.RadioInput`.
76
+ :issue:`706` :pr:`910`
77
+ - Escape double quotes in ``Markup`` attribute values
78
+ passed to :func:`~widgets.html_params`, and return a
79
+ ``Markup``. :issue:`801` :pr:`906` :pr:`907`
80
+ - Add ``test_environment`` support to :class:`~validators.Email`, and defer
81
+ to ``email_validator``'s module-level defaults for its
82
+ ``test_environment``, ``allow_smtputf8`` and ``allow_empty_local``
83
+ options. :issue:`869` :issue:`915` :pr:`894` :pr:`917`
84
+ - Add ``matcher`` and ``html_pattern`` keyword arguments to
85
+ :class:`~validators.Regexp`. ``matcher`` overrides the matching function,
86
+ :func:`re.match` by default: pass :func:`re.search` or :func:`re.fullmatch`
87
+ to change the anchoring. ``html_pattern`` controls the HTML ``pattern``
88
+ attribute emitted on supporting widgets. :issue:`867` :pr:`759` :pr:`918`
89
+ - :class:`~validators.URL` validator is based on ``urllib.parse.urlparse``
90
+ instead of a regex. New keyword arguments: ``allow_userinfo`` for
91
+ accepting ``user:password@host`` URLs; ``schemes``
92
+ (default ``("http", "https")``) is the allowlist of accepted schemes.
93
+ :pr:`847`
94
+ - Accept :class:`uuid.UUID` instances in the :class:`~validators.UUID`
95
+ validator, and translate unexpected types into
96
+ :class:`~validators.ValidationError` instead of letting
97
+ :class:`TypeError` escape. :issue:`549` :pr:`769`
98
+ - Clarify the documentation of filters, and of :class:`~fields.SelectField`
99
+ ``choices``. :issue:`859` :issue:`875` :pr:`896` :pr:`909`
100
+ - Update the Dutch and Serbian translations.
101
+ - Deprecate :class:`~fields.DateTimeField`, which will be removed in WTForms
102
+ 3.4. :issue:`831` :pr:`897`
103
+ - Passing :class:`~fields.SelectField` ``choices`` as tuples, or as a dict
104
+ that is not the shorthand syntax, is deprecated and will be removed in
105
+ WTForms 3.4. Use :class:`~fields.SelectChoice` instead. :issue:`922`
106
+ - Passing a callable to ``SelectFieldBase._choices_from_input`` is
107
+ deprecated and will be removed in WTForms 3.4.
108
+ - For :class:`~fields.SelectField` subclasses, yielding raw tuples from
109
+ ``iter_choices`` or
110
+ ``iter_groups``, and overriding
111
+ ``Select.render_option`` with the pre-3.3 signature, are
112
+ deprecated and will be removed in WTForms 4.0. :issue:`922`
113
+
114
+ Version 3.2.2
115
+ -------------
116
+
117
+ Released 2026-05-03
118
+
119
+ - Fix :class:`~validators.Disabled` validation with provided formdata. :pr:`880`
120
+ - End support for Python 3.9, start support for Python 3.14. :pr:`883`
121
+ - Add Tamil and Serbian translations.
122
+
3
123
  Version 3.2.1
4
124
  -------------
5
125
 
@@ -35,7 +155,6 @@ Released 2024-10-20
35
155
  If you need to keep the old behavior you can set the ``_form_error_key``
36
156
  parameter of your form to :data:`None`.
37
157
 
38
-
39
158
  Version 3.1.2
40
159
  -------------
41
160
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.5
2
2
  Name: WTForms
3
- Version: 3.2.1
3
+ Version: 3.3.0
4
4
  Summary: Form validation and rendering for Python web development.
5
5
  Project-URL: Documentation, https://wtforms.readthedocs.io
6
6
  Project-URL: Changes, https://wtforms.readthedocs.io/changes
@@ -44,10 +44,10 @@ Classifier: License :: OSI Approved :: BSD License
44
44
  Classifier: Operating System :: OS Independent
45
45
  Classifier: Programming Language :: Python
46
46
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
47
- Requires-Python: >=3.9
48
- Requires-Dist: markupsafe
47
+ Requires-Python: >=3.11
48
+ Requires-Dist: markupsafe>=1.1.1
49
49
  Provides-Extra: email
50
- Requires-Dist: email-validator; extra == 'email'
50
+ Requires-Dist: email-validator>=2.0; extra == 'email'
51
51
  Description-Content-Type: text/x-rst
52
52
 
53
53
  WTForms
@@ -86,11 +86,6 @@ with frameworks even better.
86
86
  validators.
87
87
  - `WTForms-SQLAlchemy`_ provides ORM-backed fields and form generation
88
88
  from SQLAlchemy models.
89
- - `WTForms-AppEngine`_ provides ORM-backed fields and form generation
90
- from AppEnding db/ndb schema
91
- - `WTForms-Django`_ provides ORM-backed fields and form generation
92
- from Django models, as well as integration with Django's I18N
93
- support.
94
89
  - `WTForms-Bootstrap5`_ provides Bootstrap 5 favor renderer with
95
90
  great customizability.
96
91
  - `Starlette-WTF`_ integrates with Starlette and the FastAPI
@@ -101,8 +96,6 @@ with frameworks even better.
101
96
  .. _Flask-WTF: https://flask-wtf.readthedocs.io/
102
97
  .. _WTForms-Alchemy: https://wtforms-alchemy.readthedocs.io/
103
98
  .. _WTForms-SQLAlchemy: https://github.com/pallets-eco/wtforms-sqlalchemy
104
- .. _WTForms-AppEngine: https://github.com/pallets-eco/wtforms-appengine
105
- .. _WTForms-Django: https://github.com/pallets-eco/wtforms-django
106
99
  .. _WTForms-Bootstrap5: https://github.com/LaunchPlatform/wtforms-bootstrap5
107
100
  .. _Starlette-WTF: https://github.com/muicss/starlette-wtf
108
101
  .. _Bootstrap-Flask: https://github.com/helloflask/bootstrap-flask
@@ -34,11 +34,6 @@ with frameworks even better.
34
34
  validators.
35
35
  - `WTForms-SQLAlchemy`_ provides ORM-backed fields and form generation
36
36
  from SQLAlchemy models.
37
- - `WTForms-AppEngine`_ provides ORM-backed fields and form generation
38
- from AppEnding db/ndb schema
39
- - `WTForms-Django`_ provides ORM-backed fields and form generation
40
- from Django models, as well as integration with Django's I18N
41
- support.
42
37
  - `WTForms-Bootstrap5`_ provides Bootstrap 5 favor renderer with
43
38
  great customizability.
44
39
  - `Starlette-WTF`_ integrates with Starlette and the FastAPI
@@ -49,8 +44,6 @@ with frameworks even better.
49
44
  .. _Flask-WTF: https://flask-wtf.readthedocs.io/
50
45
  .. _WTForms-Alchemy: https://wtforms-alchemy.readthedocs.io/
51
46
  .. _WTForms-SQLAlchemy: https://github.com/pallets-eco/wtforms-sqlalchemy
52
- .. _WTForms-AppEngine: https://github.com/pallets-eco/wtforms-appengine
53
- .. _WTForms-Django: https://github.com/pallets-eco/wtforms-django
54
47
  .. _WTForms-Bootstrap5: https://github.com/LaunchPlatform/wtforms-bootstrap5
55
48
  .. _Starlette-WTF: https://github.com/muicss/starlette-wtf
56
49
  .. _Bootstrap-Flask: https://github.com/helloflask/bootstrap-flask
@@ -13,6 +13,7 @@ release, version = get_version("WTForms")
13
13
  master_doc = "index"
14
14
  extensions = [
15
15
  "sphinx.ext.autodoc",
16
+ "sphinx.ext.extlinks",
16
17
  "sphinx.ext.intersphinx",
17
18
  "sphinx.ext.viewcode",
18
19
  "pallets_sphinx_themes",
@@ -22,6 +23,20 @@ extensions = [
22
23
  intersphinx_mapping = {
23
24
  "python": ("https://docs.python.org/3/", None),
24
25
  }
26
+ extlinks = {
27
+ "mdn-tag": (
28
+ "https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/%s",
29
+ "<%s>",
30
+ ),
31
+ "mdn-attr": (
32
+ "https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/%s",
33
+ "%s",
34
+ ),
35
+ "mdn-input": (
36
+ "https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/%s",
37
+ '<input type="%s">',
38
+ ),
39
+ }
25
40
  issues_github_path = "pallets-eco/wtforms"
26
41
 
27
42
  # HTML -----------------------------------------------------------------
@@ -133,6 +133,22 @@ providing with data. Typically, you will want to assign the values manually, but
133
133
  for this simple case it's perfect. It can also be useful for CRUD and admin
134
134
  forms.
135
135
 
136
+ The same pattern extends to a collection of objects: a
137
+ :class:`~wtforms.fields.FormField` describes one item, a
138
+ :class:`~wtforms.fields.FieldList` holds the list, and ``obj`` /
139
+ ``populate_obj`` thread through both ends::
140
+
141
+ class ItemForm(Form):
142
+ name = StringField()
143
+ quantity = IntegerField()
144
+
145
+ class CartForm(Form):
146
+ items = FieldList(FormField(ItemForm))
147
+
148
+ form = CartForm(request.form, obj=cart) # cart.items == [item1, item2, ...]
149
+ if form.validate():
150
+ form.populate_obj(cart)
151
+
136
152
 
137
153
  Exploring in the console
138
154
  ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ you should have no unicode issues.
57
57
  What versions of Python are supported?
58
58
  --------------------------------------
59
59
 
60
- WTForms supports Python 3.9+
60
+ WTForms supports Python 3.10+
61
61
 
62
62
 
63
63
  How can I contribute to WTForms?