WTForms 3.3.0b4__tar.gz → 3.3.1__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.
- {wtforms-3.3.0b4 → wtforms-3.3.1}/CHANGES.rst +101 -122
- {wtforms-3.3.0b4 → wtforms-3.3.1}/PKG-INFO +1 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/whats_new.rst +16 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/__init__.py +1 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/datalist.py +6 -2
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/core.py +1 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/list.py +1 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/wtforms.pot +54 -39
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/validators.py +1 -1
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_field.py +9 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_list.py +28 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_datalist.py +24 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_url.py +8 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/.gitignore +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/LICENSE.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/README.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/Makefile +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/_static/logo_joined.svg +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/_static/logo_split.svg +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/_static/logo_square.svg +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/changes.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/conf.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/contributing.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/crash_course.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/csrf.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/ext.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/faq.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/fields.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/forms.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/i18n.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/index.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/license.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/make.bat +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/meta.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/specific_problems.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/validators.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/docs/widgets.rst +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/hatch_build.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/pyproject.toml +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/_compat.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/csrf/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/csrf/core.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/csrf/session.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/choices.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/datetime.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/form.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/numeric.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/fields/simple.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/form.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/i18n.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/README.md +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ar/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ar/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/bg/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/bg/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ca/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ca/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/cy/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/cy/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/de/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/de/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/de_CH/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/de_CH/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/el/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/el/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/en/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/en/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/es/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/es/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/et/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/et/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fa/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fa/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fi/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fi/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fr/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/fr/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/he/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/he/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/hu/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/hu/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/it/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/it/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ja/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ja/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/kk/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/kk/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ko/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ko/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/nb/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/nb/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/nl/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/nl/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/pl/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/pl/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/pt/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/pt/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ro/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ro/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ru/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ru/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sk/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sk/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sr/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sr/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sv/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/sv/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ta/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/ta/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/tr/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/tr/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/uk/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/uk/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/zh/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/zh/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/zh_TW/LC_MESSAGES/wtforms.mo +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/locale/zh_TW/LC_MESSAGES/wtforms.po +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/meta.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/utils.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/widgets/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/src/wtforms/widgets/core.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/common.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/conftest.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_boolean.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_button.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_color.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_custom.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_date.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_datetime.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_datetimelocal.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_decimal.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_defaults.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_file.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_filters.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_flags.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_float.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_form.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_hidden.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_html5.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_integer.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_label.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_month.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_password.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_radio.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_select.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_selectmultiple.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_string.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_submit.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_textarea.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_time.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/fields/test_week.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_csrf.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_form.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_i18n.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_locale_babel.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_webob.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/test_widgets.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/__init__.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_anyof.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_data_required.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_date_range.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_disabled.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_email.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_equal_to.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_input_required.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_ipaddress.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_lazy_proxy.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_length.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_mac_address.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_noneof.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_number_range.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_optional.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_readonly.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_regexp.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_uuid.py +0 -0
- {wtforms-3.3.0b4 → wtforms-3.3.1}/tests/validators/test_validators.py +0 -0
|
@@ -1,146 +1,125 @@
|
|
|
1
1
|
.. currentmodule:: wtforms
|
|
2
2
|
|
|
3
|
-
Version 3.3.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Released 2026-10-23
|
|
7
|
-
|
|
8
|
-
- Drop support for Python 3.10. Add support for Python 3.15.
|
|
9
|
-
- :func:`fields.enum_choices` and :func:`~wtforms.datalist.enum_datalist`
|
|
10
|
-
label :class:`enum.IntEnum` members with their name on PyPy too, instead of
|
|
11
|
-
their value.
|
|
12
|
-
- :class:`~datalist.DataList` ``choices`` accepts the shorthand
|
|
13
|
-
``{value: label}`` dict syntax. :issue:`886`
|
|
14
|
-
- Default ``invalid_value_message`` and ``invalid_choice_message`` are
|
|
15
|
-
translated when the error is raised, not when the field is built. Forms can
|
|
16
|
-
be built again outside of a translation context.
|
|
17
|
-
- ``choices`` callables on :class:`~fields.SelectField` and
|
|
18
|
-
:class:`~datalist.DataList` run on the first read and their result is
|
|
19
|
-
cached. Calling :meth:`~form.BaseForm.post_process` again refreshes them.
|
|
20
|
-
This also applies to entries added with
|
|
21
|
-
:meth:`~fields.FieldList.append_entry` and
|
|
22
|
-
:meth:`~fields.FieldList.insert_entry`.
|
|
23
|
-
- Passing a callable to ``SelectFieldBase._choices_from_input`` is
|
|
24
|
-
deprecated.
|
|
25
|
-
- Numeric, date, time and select fields report a validation error instead of
|
|
26
|
-
raising a :class:`TypeError` when the input is not a string.
|
|
27
|
-
- The labels of :class:`~fields.FieldList` entries point to the right field
|
|
28
|
-
after :meth:`~fields.FieldList.insert_entry` or
|
|
29
|
-
:meth:`~fields.FieldList.pop_entry` renumbers the entries.
|
|
30
|
-
|
|
31
|
-
Version 3.3.0b3
|
|
32
|
-
---------------
|
|
3
|
+
Version 3.3.1
|
|
4
|
+
-------------
|
|
33
5
|
|
|
34
|
-
Released 2026-
|
|
6
|
+
Released 2026-10-24
|
|
35
7
|
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
``member.value``. :issue:`922`
|
|
8
|
+
- Fix :class:`~fields.FieldList` entries losing the form prefix in their
|
|
9
|
+
``name`` when the list renumbers them. :issue:`944`
|
|
10
|
+
- Speed up :class:`~validators.URL` on hostnames with many consecutive
|
|
11
|
+
dashes. :issue:`945`
|
|
41
12
|
|
|
42
|
-
Version 3.3.
|
|
43
|
-
|
|
13
|
+
Version 3.3.0
|
|
14
|
+
-------------
|
|
44
15
|
|
|
45
|
-
Released 2026-
|
|
16
|
+
Released 2026-10-23
|
|
46
17
|
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
18
|
+
- Drop support for Python 3.10. Add support for Python 3.15.
|
|
19
|
+
- Add native :class:`DataList` support. Options are declared with
|
|
20
|
+
:class:`DataListChoice`, or with the shorthand ``{value: label}``
|
|
21
|
+
dict syntax. :issue:`653` :issue:`886` :pr:`921`
|
|
22
|
+
- Add :class:`~fields.ButtonField` to render ``<button type="submit">``
|
|
23
|
+
controls with string values. :issue:`784` :pr:`892`
|
|
24
|
+
- Add :class:`~validators.DateRange`. ``min`` and ``max`` may be callables
|
|
25
|
+
to compute dynamic bounds; :class:`~validators.NumberRange` accepts
|
|
26
|
+
callables on the same terms. :pr:`787`
|
|
27
|
+
- Add :class:`~fields.FieldList` ``insert_entry`` and indexed ``pop_entry``.
|
|
28
|
+
The following entries are renumbered, with their ids and labels.
|
|
29
|
+
:issue:`256` :pr:`901` :pr:`912`
|
|
30
|
+
- :class:`~fields.SelectField` refactor. Options are declared with
|
|
31
|
+
:class:`~fields.SelectChoice`, which takes HTML attributes in
|
|
32
|
+
``render_kw`` and an ``optgroup``. ``iter_choices``
|
|
33
|
+
and ``iter_groups`` yield
|
|
34
|
+
:class:`~fields.Choice` objects. ``choices`` also accepts the shorthand
|
|
35
|
+
dict syntax: ``{value: label}`` for flat options and
|
|
36
|
+
``{label: {value: label}}`` for optgroups. :issue:`692` :issue:`886`
|
|
37
|
+
:issue:`922` :pr:`739` :pr:`889`
|
|
54
38
|
- ``choices`` callables on :class:`~fields.SelectField` and
|
|
55
|
-
:class
|
|
56
|
-
|
|
39
|
+
:class:`DataList` may accept ``(form, field)``. They run on the
|
|
40
|
+
first read and their result is cached. Calling
|
|
41
|
+
:meth:`~form.BaseForm.post_process` again refreshes them, also for the
|
|
42
|
+
entries added with :meth:`~fields.FieldList.append_entry` and
|
|
43
|
+
:meth:`~fields.FieldList.insert_entry`. :issue:`922`
|
|
44
|
+
- Add :func:`fields.enum_choices`, :func:`fields.enum_coerce` and
|
|
45
|
+
:func:`~datalist.enum_datalist` for Enum-backed choices. :issue:`338`
|
|
46
|
+
:issue:`922` :pr:`916`
|
|
57
47
|
- Add :meth:`fields.Field.post_process` and
|
|
58
48
|
:meth:`form.BaseForm.post_process` hooks, propagated through
|
|
59
|
-
:class:`~fields.FormField` and :class:`~fields.FieldList
|
|
49
|
+
:class:`~fields.FormField` and :class:`~fields.FieldList`, for
|
|
60
50
|
cross-field finalization. :issue:`922`
|
|
61
51
|
- Add ``Field._form`` and ``BaseForm._parent_form`` so fields and nested
|
|
62
|
-
forms can reach their enclosing form.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- Add :class:`~validators.DateRange`. ``min`` and ``max`` may be callables
|
|
80
|
-
to compute dynamic bounds; :class:`~validators.NumberRange` accepts
|
|
81
|
-
callables on the same terms. :pr:`787`
|
|
52
|
+
forms can reach their enclosing form. :class:`~fields.FieldList` entries
|
|
53
|
+
and :class:`~fields.SelectField` option subfields no longer get
|
|
54
|
+
``form=None``. :issue:`922`
|
|
55
|
+
- Add ``invalid_value_message`` and ``invalid_choice_message`` keyword
|
|
56
|
+
arguments for customizing built-in field error messages. On
|
|
57
|
+
:class:`~fields.SelectMultipleField`, ``invalid_choice_message`` may also
|
|
58
|
+
be a callable for custom pluralization. :issue:`39` :issue:`832` :pr:`902`
|
|
59
|
+
- :class:`~fields.SelectField` and :class:`~fields.SelectMultipleField`
|
|
60
|
+
``pre_validate`` short-circuits when ``process_formdata`` already produced
|
|
61
|
+
an error, so a single coercion failure no longer surfaces as both an
|
|
62
|
+
"invalid value" and an "invalid choice" error. :pr:`902`
|
|
63
|
+
- Numeric, date, time and select fields report a validation error instead of
|
|
64
|
+
raising a :class:`TypeError` when the input is not a string. :pr:`936`
|
|
65
|
+
- Each bound field gets its own copy of ``render_kw``, and so does its
|
|
66
|
+
:class:`DataList`. Changing one of them on a form instance no
|
|
67
|
+
longer changes it on the other ones. :issue:`942`
|
|
82
68
|
- Make :class:`~fields.FloatField` render as ``<input type="number">`` with
|
|
83
69
|
``step="any"``. :issue:`677` :pr:`679`
|
|
84
|
-
- :
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
:
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
and translate unexpected types into :class:`~validators.ValidationError`
|
|
99
|
-
instead of letting :class:`TypeError` escape. :issue:`549` :pr:`769`
|
|
100
|
-
- Escape double quotes in :class:`~markupsafe.Markup` attribute values
|
|
101
|
-
passed to :func:`~widgets.html_params`, and return a
|
|
102
|
-
:class:`~markupsafe.Markup`. :issue:`801` :pr:`906` :pr:`907`
|
|
103
|
-
- Clarify documentation about filters. :issue:`859` :pr:`896`
|
|
70
|
+
- Add a ``tz`` parameter to :class:`~fields.DateTimeLocalField` to associate a
|
|
71
|
+
timezone with the input. :issue:`833` :pr:`905`
|
|
72
|
+
- Let :class:`~widgets.RangeInput` accept ``min`` and ``max`` at construction
|
|
73
|
+
time. :issue:`693` :pr:`898`
|
|
74
|
+
- ``FieldList._add_entry`` routes through
|
|
75
|
+
:meth:`~meta.DefaultMeta.bind_field`, like the top-level fields. Custom
|
|
76
|
+
``Meta.bind_field`` overrides were silently bypassed for
|
|
77
|
+
:class:`~fields.FieldList` entries. :pr:`891`
|
|
78
|
+
- Reset :class:`~fields.FieldList` index state when reprocessing entries.
|
|
79
|
+
:issue:`874` :pr:`895`
|
|
80
|
+
- Do not render a ``for`` attribute on the main label of
|
|
81
|
+
:class:`~fields.RadioField`. :issue:`775` :pr:`900`
|
|
82
|
+
- Render ``False`` as ``value="False"`` in :class:`~fields.SelectField`
|
|
83
|
+
options instead of omitting the attribute. :issue:`878` :pr:`908`
|
|
104
84
|
- Let render-time ``checked`` kwargs take precedence over the field's value
|
|
105
85
|
in :class:`~widgets.CheckboxInput` and :class:`~widgets.RadioInput`.
|
|
106
86
|
:issue:`706` :pr:`910`
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Enum class as ``coerce``. :issue:`338` :pr:`916`
|
|
120
|
-
- Defer to ``email_validator``'s module-level defaults for the
|
|
121
|
-
:class:`~validators.Email` ``test_environment``, ``allow_smtputf8`` and
|
|
122
|
-
``allow_empty_local`` options. :issue:`915` :pr:`917`
|
|
123
|
-
- Add ``invalid_value_message`` and ``invalid_choice_message`` keyword
|
|
124
|
-
arguments for customizing built-in field error messages. On
|
|
125
|
-
``SelectMultipleField``, ``invalid_choice_message`` may also be a callable
|
|
126
|
-
for custom pluralization. :issue:`39` :issue:`832` :pr:`902`
|
|
127
|
-
- :class:`~fields.SelectField` and :class:`~fields.SelectMultipleField`
|
|
128
|
-
``pre_validate`` now short-circuits when ``process_formdata`` already
|
|
129
|
-
produced an error, so a single coercion failure no longer surfaces as both
|
|
130
|
-
an "invalid value" and an "invalid choice" error. :pr:`902`
|
|
131
|
-
- Add a ``matcher`` keyword argument to :class:`~validators.Regexp` to
|
|
132
|
-
override the matching function. Defaults to :func:`re.match`; pass
|
|
133
|
-
:func:`re.search` or :func:`re.fullmatch` to change the anchoring
|
|
134
|
-
behaviour. :issue:`867` :pr:`918`
|
|
135
|
-
- Add an ``html_pattern`` keyword argument to :class:`~validators.Regexp`
|
|
136
|
-
to control the HTML ``pattern`` attribute emitted on supporting widgets.
|
|
137
|
-
:pr:`759`
|
|
87
|
+
- Escape double quotes in ``Markup`` attribute values
|
|
88
|
+
passed to :func:`~widgets.html_params`, and return a
|
|
89
|
+
``Markup``. :issue:`801` :pr:`906` :pr:`907`
|
|
90
|
+
- Add ``test_environment`` support to :class:`~validators.Email`, and defer
|
|
91
|
+
to ``email_validator``'s module-level defaults for its
|
|
92
|
+
``test_environment``, ``allow_smtputf8`` and ``allow_empty_local``
|
|
93
|
+
options. :issue:`869` :issue:`915` :pr:`894` :pr:`917`
|
|
94
|
+
- Add ``matcher`` and ``html_pattern`` keyword arguments to
|
|
95
|
+
:class:`~validators.Regexp`. ``matcher`` overrides the matching function,
|
|
96
|
+
:func:`re.match` by default: pass :func:`re.search` or :func:`re.fullmatch`
|
|
97
|
+
to change the anchoring. ``html_pattern`` controls the HTML ``pattern``
|
|
98
|
+
attribute emitted on supporting widgets. :issue:`867` :pr:`759` :pr:`918`
|
|
138
99
|
- :class:`~validators.URL` validator is based on ``urllib.parse.urlparse``
|
|
139
100
|
instead of a regex. New keyword arguments: ``allow_userinfo`` for
|
|
140
101
|
accepting ``user:password@host`` URLs; ``schemes``
|
|
141
|
-
(default ``("http", "https")``) is the allowlist of accepted schemes
|
|
102
|
+
(default ``("http", "https")``) is the allowlist of accepted schemes.
|
|
142
103
|
:pr:`847`
|
|
143
|
-
-
|
|
104
|
+
- Accept :class:`uuid.UUID` instances in the :class:`~validators.UUID`
|
|
105
|
+
validator, and translate unexpected types into
|
|
106
|
+
:class:`~validators.ValidationError` instead of letting
|
|
107
|
+
:class:`TypeError` escape. :issue:`549` :pr:`769`
|
|
108
|
+
- Clarify the documentation of filters, and of :class:`~fields.SelectField`
|
|
109
|
+
``choices``. :issue:`859` :issue:`875` :pr:`896` :pr:`909`
|
|
110
|
+
- Update the Dutch and Serbian translations.
|
|
111
|
+
- Deprecate :class:`~fields.DateTimeField`, which will be removed in WTForms
|
|
112
|
+
3.4. :issue:`831` :pr:`897`
|
|
113
|
+
- Passing :class:`~fields.SelectField` ``choices`` as tuples, or as a dict
|
|
114
|
+
that is not the shorthand syntax, is deprecated and will be removed in
|
|
115
|
+
WTForms 3.4. Use :class:`~fields.SelectChoice` instead. :issue:`922`
|
|
116
|
+
- Passing a callable to ``SelectFieldBase._choices_from_input`` is
|
|
117
|
+
deprecated and will be removed in WTForms 3.4.
|
|
118
|
+
- For :class:`~fields.SelectField` subclasses, yielding raw tuples from
|
|
119
|
+
``iter_choices`` or
|
|
120
|
+
``iter_groups``, and overriding
|
|
121
|
+
``Select.render_option`` with the pre-3.3 signature, are
|
|
122
|
+
deprecated and will be removed in WTForms 4.0. :issue:`922`
|
|
144
123
|
|
|
145
124
|
Version 3.2.2
|
|
146
125
|
-------------
|
|
@@ -4,7 +4,22 @@ What's New in WTForms 3
|
|
|
4
4
|
New Features
|
|
5
5
|
------------
|
|
6
6
|
|
|
7
|
-
WTForms 3
|
|
7
|
+
WTForms 3.3 adds:
|
|
8
|
+
|
|
9
|
+
- native :class:`~wtforms.DataList` support, to suggest values in a text
|
|
10
|
+
input;
|
|
11
|
+
- :class:`~wtforms.fields.ButtonField`, to render ``<button type="submit">``
|
|
12
|
+
controls;
|
|
13
|
+
- the :class:`~wtforms.validators.DateRange` validator;
|
|
14
|
+
- :meth:`~wtforms.fields.FieldList.insert_entry` and an indexed
|
|
15
|
+
:meth:`~wtforms.fields.FieldList.pop_entry`;
|
|
16
|
+
- a reworked :class:`~wtforms.fields.SelectField`: options are declared with
|
|
17
|
+
:class:`~wtforms.fields.SelectChoice`, which takes HTML attributes and an
|
|
18
|
+
optgroup, and ``choices`` callables run on the first read;
|
|
19
|
+
- :meth:`~wtforms.form.BaseForm.post_process` hooks for cross-field
|
|
20
|
+
finalization.
|
|
21
|
+
|
|
22
|
+
See :doc:`changes` for the full list, including the deprecations.
|
|
8
23
|
|
|
9
24
|
|
|
10
25
|
Past Major Releases
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from dataclasses import field
|
|
4
|
+
from dataclasses import replace
|
|
4
5
|
|
|
5
6
|
from wtforms import widgets
|
|
6
7
|
from wtforms.fields.choices import _enum_options
|
|
@@ -103,7 +104,7 @@ class DataList:
|
|
|
103
104
|
clone._raw_choices = self._raw_choices
|
|
104
105
|
clone._choices = None if callable(self._raw_choices) else self._raw_choices
|
|
105
106
|
clone._field = None
|
|
106
|
-
clone.render_kw = self.render_kw
|
|
107
|
+
clone.render_kw = dict(self.render_kw)
|
|
107
108
|
clone.widget = self.widget
|
|
108
109
|
clone.id = id
|
|
109
110
|
return clone
|
|
@@ -126,7 +127,10 @@ class DataList:
|
|
|
126
127
|
return [
|
|
127
128
|
DataListChoice(value=value, label=label) for value, label in raw.items()
|
|
128
129
|
]
|
|
129
|
-
return [
|
|
130
|
+
return [
|
|
131
|
+
replace(choice, render_kw=dict(choice.render_kw or {}))
|
|
132
|
+
for choice in map(DataListChoice.from_input, raw)
|
|
133
|
+
]
|
|
130
134
|
|
|
131
135
|
def __call__(self, field=None, **kwargs):
|
|
132
136
|
return self.widget(self, field=field, **kwargs)
|
|
@@ -115,7 +115,7 @@ class Field:
|
|
|
115
115
|
self.default = default
|
|
116
116
|
self.description = description
|
|
117
117
|
self.invalid_value_message = invalid_value_message
|
|
118
|
-
self.render_kw = render_kw
|
|
118
|
+
self.render_kw = dict(render_kw) if render_kw is not None else None
|
|
119
119
|
self.filters = filters
|
|
120
120
|
self.flags = Flags()
|
|
121
121
|
self.name = _prefix + name
|
|
@@ -195,7 +195,7 @@ class FieldList(Field):
|
|
|
195
195
|
"""Rename ``entry`` to ``new_index`` and propagate to its descendants."""
|
|
196
196
|
old_name = entry.name
|
|
197
197
|
old_id = entry.id
|
|
198
|
-
new_name = f"{self.
|
|
198
|
+
new_name = f"{self.name}{self._separator}{new_index}"
|
|
199
199
|
new_id = f"{self.id}{self._separator}{new_index}"
|
|
200
200
|
|
|
201
201
|
if old_name == new_name and old_id == new_id and entry.index == new_index:
|
|
@@ -1,116 +1,131 @@
|
|
|
1
1
|
# Translations template for WTForms.
|
|
2
|
-
# Copyright (C)
|
|
2
|
+
# Copyright (C) 2026 WTForms Team
|
|
3
3
|
# This file is distributed under the same license as the WTForms project.
|
|
4
|
-
# FIRST AUTHOR <EMAIL@ADDRESS>,
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, 2026.
|
|
5
5
|
#
|
|
6
6
|
#, fuzzy
|
|
7
7
|
msgid ""
|
|
8
8
|
msgstr ""
|
|
9
9
|
"Project-Id-Version: WTForms 3.0.0\n"
|
|
10
10
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
|
11
|
-
"POT-Creation-Date:
|
|
11
|
+
"POT-Creation-Date: 2026-10-23 16:37+0200\n"
|
|
12
12
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
13
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
14
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
15
15
|
"MIME-Version: 1.0\n"
|
|
16
16
|
"Content-Type: text/plain; charset=utf-8\n"
|
|
17
17
|
"Content-Transfer-Encoding: 8bit\n"
|
|
18
|
-
"Generated-By: Babel 2.
|
|
18
|
+
"Generated-By: Babel 2.18.0\n"
|
|
19
19
|
|
|
20
|
-
#: src/wtforms/validators.py:
|
|
20
|
+
#: src/wtforms/validators.py:93
|
|
21
21
|
#, python-format
|
|
22
22
|
msgid "Invalid field name '%s'."
|
|
23
23
|
msgstr ""
|
|
24
24
|
|
|
25
|
-
#: src/wtforms/validators.py:
|
|
25
|
+
#: src/wtforms/validators.py:106
|
|
26
26
|
#, python-format
|
|
27
27
|
msgid "Field must be equal to %(other_name)s."
|
|
28
28
|
msgstr ""
|
|
29
29
|
|
|
30
|
-
#: src/wtforms/validators.py:
|
|
30
|
+
#: src/wtforms/validators.py:153
|
|
31
31
|
#, python-format
|
|
32
32
|
msgid "Field must be at least %(min)d character long."
|
|
33
33
|
msgid_plural "Field must be at least %(min)d characters long."
|
|
34
34
|
msgstr[0] ""
|
|
35
35
|
msgstr[1] ""
|
|
36
36
|
|
|
37
|
-
#: src/wtforms/validators.py:
|
|
37
|
+
#: src/wtforms/validators.py:159
|
|
38
38
|
#, python-format
|
|
39
39
|
msgid "Field cannot be longer than %(max)d character."
|
|
40
40
|
msgid_plural "Field cannot be longer than %(max)d characters."
|
|
41
41
|
msgstr[0] ""
|
|
42
42
|
msgstr[1] ""
|
|
43
43
|
|
|
44
|
-
#: src/wtforms/validators.py:
|
|
44
|
+
#: src/wtforms/validators.py:165
|
|
45
45
|
#, python-format
|
|
46
46
|
msgid "Field must be exactly %(max)d character long."
|
|
47
47
|
msgid_plural "Field must be exactly %(max)d characters long."
|
|
48
48
|
msgstr[0] ""
|
|
49
49
|
msgstr[1] ""
|
|
50
50
|
|
|
51
|
-
#: src/wtforms/validators.py:
|
|
51
|
+
#: src/wtforms/validators.py:171
|
|
52
52
|
#, python-format
|
|
53
53
|
msgid "Field must be between %(min)d and %(max)d characters long."
|
|
54
54
|
msgstr ""
|
|
55
55
|
|
|
56
|
-
#: src/wtforms/validators.py:
|
|
56
|
+
#: src/wtforms/validators.py:233
|
|
57
57
|
#, python-format
|
|
58
58
|
msgid "Number must be at least %(min)s."
|
|
59
59
|
msgstr ""
|
|
60
60
|
|
|
61
|
-
#: src/wtforms/validators.py:
|
|
61
|
+
#: src/wtforms/validators.py:236
|
|
62
62
|
#, python-format
|
|
63
63
|
msgid "Number must be at most %(max)s."
|
|
64
64
|
msgstr ""
|
|
65
65
|
|
|
66
|
-
#: src/wtforms/validators.py:
|
|
66
|
+
#: src/wtforms/validators.py:239
|
|
67
67
|
#, python-format
|
|
68
68
|
msgid "Number must be between %(min)s and %(max)s."
|
|
69
69
|
msgstr ""
|
|
70
70
|
|
|
71
|
-
#: src/wtforms/validators.py:
|
|
71
|
+
#: src/wtforms/validators.py:328
|
|
72
|
+
#, python-format
|
|
73
|
+
msgid "Date must be at least %(min)s."
|
|
74
|
+
msgstr ""
|
|
75
|
+
|
|
76
|
+
#: src/wtforms/validators.py:331
|
|
77
|
+
#, python-format
|
|
78
|
+
msgid "Date must be at most %(max)s."
|
|
79
|
+
msgstr ""
|
|
80
|
+
|
|
81
|
+
#: src/wtforms/validators.py:334
|
|
82
|
+
#, python-format
|
|
83
|
+
msgid "Date must be between %(min)s and %(max)s."
|
|
84
|
+
msgstr ""
|
|
85
|
+
|
|
86
|
+
#: src/wtforms/validators.py:405 src/wtforms/validators.py:435
|
|
72
87
|
msgid "This field is required."
|
|
73
88
|
msgstr ""
|
|
74
89
|
|
|
75
|
-
#: src/wtforms/validators.py:
|
|
90
|
+
#: src/wtforms/validators.py:504
|
|
76
91
|
msgid "Invalid input."
|
|
77
92
|
msgstr ""
|
|
78
93
|
|
|
79
|
-
#: src/wtforms/validators.py:
|
|
94
|
+
#: src/wtforms/validators.py:581
|
|
80
95
|
msgid "Invalid email address."
|
|
81
96
|
msgstr ""
|
|
82
97
|
|
|
83
|
-
#: src/wtforms/validators.py:
|
|
98
|
+
#: src/wtforms/validators.py:619
|
|
84
99
|
msgid "Invalid IP address."
|
|
85
100
|
msgstr ""
|
|
86
101
|
|
|
87
|
-
#: src/wtforms/validators.py:
|
|
102
|
+
#: src/wtforms/validators.py:662
|
|
88
103
|
msgid "Invalid Mac address."
|
|
89
104
|
msgstr ""
|
|
90
105
|
|
|
91
|
-
#: src/wtforms/validators.py:
|
|
106
|
+
#: src/wtforms/validators.py:710
|
|
92
107
|
msgid "Invalid URL."
|
|
93
108
|
msgstr ""
|
|
94
109
|
|
|
95
|
-
#: src/wtforms/validators.py:
|
|
110
|
+
#: src/wtforms/validators.py:749
|
|
96
111
|
msgid "Invalid UUID."
|
|
97
112
|
msgstr ""
|
|
98
113
|
|
|
99
|
-
#: src/wtforms/validators.py:
|
|
114
|
+
#: src/wtforms/validators.py:787
|
|
100
115
|
#, python-format
|
|
101
116
|
msgid "Invalid value, must be one of: %(values)s."
|
|
102
117
|
msgstr ""
|
|
103
118
|
|
|
104
|
-
#: src/wtforms/validators.py:
|
|
119
|
+
#: src/wtforms/validators.py:823
|
|
105
120
|
#, python-format
|
|
106
121
|
msgid "Invalid value, can't be any of: %(values)s."
|
|
107
122
|
msgstr ""
|
|
108
123
|
|
|
109
|
-
#: src/wtforms/validators.py:
|
|
124
|
+
#: src/wtforms/validators.py:892
|
|
110
125
|
msgid "This field cannot be edited."
|
|
111
126
|
msgstr ""
|
|
112
127
|
|
|
113
|
-
#: src/wtforms/validators.py:
|
|
128
|
+
#: src/wtforms/validators.py:908
|
|
114
129
|
msgid "This field is disabled and cannot have a value."
|
|
115
130
|
msgstr ""
|
|
116
131
|
|
|
@@ -118,65 +133,65 @@ msgstr ""
|
|
|
118
133
|
msgid "Invalid CSRF Token."
|
|
119
134
|
msgstr ""
|
|
120
135
|
|
|
121
|
-
#: src/wtforms/csrf/session.py:
|
|
136
|
+
#: src/wtforms/csrf/session.py:64
|
|
122
137
|
msgid "CSRF token missing."
|
|
123
138
|
msgstr ""
|
|
124
139
|
|
|
125
|
-
#: src/wtforms/csrf/session.py:
|
|
140
|
+
#: src/wtforms/csrf/session.py:72
|
|
126
141
|
msgid "CSRF failed."
|
|
127
142
|
msgstr ""
|
|
128
143
|
|
|
129
|
-
#: src/wtforms/csrf/session.py:
|
|
144
|
+
#: src/wtforms/csrf/session.py:77
|
|
130
145
|
msgid "CSRF token expired."
|
|
131
146
|
msgstr ""
|
|
132
147
|
|
|
133
|
-
#: src/wtforms/fields/choices.py:
|
|
148
|
+
#: src/wtforms/fields/choices.py:480
|
|
134
149
|
msgid "Invalid Choice: could not coerce."
|
|
135
150
|
msgstr ""
|
|
136
151
|
|
|
137
|
-
#: src/wtforms/fields/choices.py:
|
|
152
|
+
#: src/wtforms/fields/choices.py:491 src/wtforms/fields/choices.py:590
|
|
138
153
|
msgid "Choices cannot be None."
|
|
139
154
|
msgstr ""
|
|
140
155
|
|
|
141
|
-
#: src/wtforms/fields/choices.py:
|
|
156
|
+
#: src/wtforms/fields/choices.py:495
|
|
142
157
|
msgid "Not a valid choice."
|
|
143
158
|
msgstr ""
|
|
144
159
|
|
|
145
|
-
#: src/wtforms/fields/choices.py:
|
|
160
|
+
#: src/wtforms/fields/choices.py:578
|
|
146
161
|
msgid "Invalid choice(s): one or more data inputs could not be coerced."
|
|
147
162
|
msgstr ""
|
|
148
163
|
|
|
149
|
-
#: src/wtforms/fields/choices.py:
|
|
164
|
+
#: src/wtforms/fields/choices.py:605
|
|
150
165
|
#, python-format
|
|
151
166
|
msgid "'%(value)s' is not a valid choice for this field."
|
|
152
167
|
msgid_plural "'%(value)s' are not valid choices for this field."
|
|
153
168
|
msgstr[0] ""
|
|
154
169
|
msgstr[1] ""
|
|
155
170
|
|
|
156
|
-
#: src/wtforms/fields/datetime.py:
|
|
171
|
+
#: src/wtforms/fields/datetime.py:74
|
|
157
172
|
msgid "Not a valid datetime value."
|
|
158
173
|
msgstr ""
|
|
159
174
|
|
|
160
|
-
#: src/wtforms/fields/datetime.py:
|
|
175
|
+
#: src/wtforms/fields/datetime.py:115
|
|
161
176
|
msgid "Not a valid date value."
|
|
162
177
|
msgstr ""
|
|
163
178
|
|
|
164
|
-
#: src/wtforms/fields/datetime.py:
|
|
179
|
+
#: src/wtforms/fields/datetime.py:156
|
|
165
180
|
msgid "Not a valid time value."
|
|
166
181
|
msgstr ""
|
|
167
182
|
|
|
168
|
-
#: src/wtforms/fields/datetime.py:
|
|
183
|
+
#: src/wtforms/fields/datetime.py:218
|
|
169
184
|
msgid "Not a valid week value."
|
|
170
185
|
msgstr ""
|
|
171
186
|
|
|
172
|
-
#: src/wtforms/fields/numeric.py:
|
|
187
|
+
#: src/wtforms/fields/numeric.py:86 src/wtforms/fields/numeric.py:98
|
|
173
188
|
msgid "Not a valid integer value."
|
|
174
189
|
msgstr ""
|
|
175
190
|
|
|
176
|
-
#: src/wtforms/fields/numeric.py:
|
|
191
|
+
#: src/wtforms/fields/numeric.py:183
|
|
177
192
|
msgid "Not a valid decimal value."
|
|
178
193
|
msgstr ""
|
|
179
194
|
|
|
180
|
-
#: src/wtforms/fields/numeric.py:
|
|
195
|
+
#: src/wtforms/fields/numeric.py:220
|
|
181
196
|
msgid "Not a valid float value."
|
|
182
197
|
msgstr ""
|
|
@@ -836,7 +836,7 @@ class HostnameValidation:
|
|
|
836
836
|
This is not a validator in and of itself, and as such is not exported.
|
|
837
837
|
"""
|
|
838
838
|
|
|
839
|
-
hostname_part = re.compile(r"^(xn-|[a-z0-9_]+)(-[a-z0-9_-]+)
|
|
839
|
+
hostname_part = re.compile(r"^(xn-|[a-z0-9_]+)(-[a-z0-9_-]+)?$", re.IGNORECASE)
|
|
840
840
|
tld_part = re.compile(r"^([a-z]{2,20}|xn--([a-z0-9]+-)*[a-z0-9]+)$", re.IGNORECASE)
|
|
841
841
|
|
|
842
842
|
def __init__(self, require_tld=True, allow_ip=False):
|
|
@@ -77,6 +77,15 @@ def test_render_kw():
|
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
|
|
80
|
+
def test_render_kw_is_not_shared_between_form_instances():
|
|
81
|
+
"""Changing render_kw on one form instance does not change it on the others."""
|
|
82
|
+
first, second = F(), F()
|
|
83
|
+
first.a.render_kw["readonly"] = False
|
|
84
|
+
del first.a.render_kw["foo"]
|
|
85
|
+
assert second.a.render_kw == {"readonly": True, "foo": "bar"}
|
|
86
|
+
assert F.a.kwargs["render_kw"] == {"readonly": True, "foo": "bar"}
|
|
87
|
+
|
|
88
|
+
|
|
80
89
|
def test_render_special():
|
|
81
90
|
class F(Form):
|
|
82
91
|
s = StringField(render_kw={"class_": "foo"})
|
|
@@ -236,6 +236,34 @@ def test_renumbered_entries_keep_their_labels_in_sync():
|
|
|
236
236
|
assert [e.foo.label.field_id for e in form.b.entries] == ["b-0-foo"]
|
|
237
237
|
|
|
238
238
|
|
|
239
|
+
def test_renumbered_entries_keep_the_form_prefix():
|
|
240
|
+
"""Renumbered entries keep the form prefix in their name."""
|
|
241
|
+
F = make_form(a=FieldList(t, min_entries=2))
|
|
242
|
+
|
|
243
|
+
form = F(DummyPostData({"p-a-0": "x", "p-a-2": "y"}), prefix="p")
|
|
244
|
+
assert [e.name for e in form.a.entries] == ["p-a-0", "p-a-1"]
|
|
245
|
+
|
|
246
|
+
form = F(prefix="p")
|
|
247
|
+
form.a.insert_entry(0, "x")
|
|
248
|
+
assert [e.name for e in form.a.entries] == ["p-a-0", "p-a-1", "p-a-2"]
|
|
249
|
+
form.a.pop_entry(0)
|
|
250
|
+
assert [e.name for e in form.a.entries] == ["p-a-0", "p-a-1"]
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def test_renumbered_entries_in_a_subform_keep_the_subform_prefix():
|
|
254
|
+
"""Renumbered entries of a list inside a :class:`FormField` keep the
|
|
255
|
+
subform prefix in their name."""
|
|
256
|
+
|
|
257
|
+
class Inside(Form):
|
|
258
|
+
a = FieldList(FormField(make_form(foo=StringField())), min_entries=2)
|
|
259
|
+
|
|
260
|
+
F = make_form(sub=FormField(Inside))
|
|
261
|
+
form = F()
|
|
262
|
+
form.sub.a.pop_entry(0)
|
|
263
|
+
assert form.sub.a[0].name == "sub-a-0"
|
|
264
|
+
assert form.sub.a[0].foo.name == "sub-a-0-foo"
|
|
265
|
+
|
|
266
|
+
|
|
239
267
|
def test_gap_compacted_through_formdata_round_trip():
|
|
240
268
|
"""A formdata with gaps in indices is compacted on read: entries are
|
|
241
269
|
rebuilt with consecutive indices, preserving formdata key order."""
|