From be05a0c9ac735b4805322d0a0571b469b35693f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Tue, 10 Oct 2023 22:37:40 +0200 Subject: [PATCH] fix: `NoneOf` and `AnyOf` can validate multiple valued fields like `SelectMultipleField` --- CHANGES.rst | 3 +++ src/wtforms/validators.py | 6 ++++-- tests/validators/test_anyof.py | 15 +++++++++++++++ tests/validators/test_noneof.py | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d479b416b..b05d6e03a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,6 +12,9 @@ Unreleased - Removed `required` flag support from :class:`~fields.HiddenWidget`, :class:`~fields.RangeWidget` and :class:`~fields.SelectWidget` to conform to W3C :pr:`810` +- :class:`~wtforms.validators.NoneOf` and :class:`~wtforms.validators.AnyOf` + can validate multiple valued fields like :class:`~fields.SelectMultipleField` + :pr:`538` :pr:`807` Version 3.1.2 ------------- diff --git a/src/wtforms/validators.py b/src/wtforms/validators.py index d5b3c39a9..3536963bf 100644 --- a/src/wtforms/validators.py +++ b/src/wtforms/validators.py @@ -586,7 +586,8 @@ def __init__(self, values, message=None, values_formatter=None): self.values_formatter = values_formatter def __call__(self, form, field): - if field.data in self.values: + data = field.data if isinstance(field.data, list) else [field.data] + if any(d in self.values for d in data): return message = self.message @@ -621,7 +622,8 @@ def __init__(self, values, message=None, values_formatter=None): self.values_formatter = values_formatter def __call__(self, form, field): - if field.data not in self.values: + data = field.data if isinstance(field.data, list) else [field.data] + if not any(d in self.values for d in data): return message = self.message diff --git a/tests/validators/test_anyof.py b/tests/validators/test_anyof.py index eb27338e6..1a96858e2 100644 --- a/tests/validators/test_anyof.py +++ b/tests/validators/test_anyof.py @@ -39,3 +39,18 @@ def formatter(values): validator(dummy_form, dummy_field) assert str(e.value) == "test 9::8::7" + + +def test_none_multiple_values(dummy_form, dummy_field): + """ + the validator should work with multiple values like produced + by SelectMultiple fields + """ + dummy_field.data = ["a", "e"] + validator = AnyOf(["a", "b", "c"]) + validator(dummy_form, dummy_field) + + dummy_field.data = ["d", "e"] + validator = AnyOf(["a", "b", "c"]) + with pytest.raises(ValueError): + validator(dummy_form, dummy_field) diff --git a/tests/validators/test_noneof.py b/tests/validators/test_noneof.py index 13bde92ea..efd989e92 100644 --- a/tests/validators/test_noneof.py +++ b/tests/validators/test_noneof.py @@ -20,3 +20,18 @@ def test_none_of_raises(dummy_form, dummy_field): validator = NoneOf(["a", "b", "c"]) with pytest.raises(ValueError): validator(dummy_form, dummy_field) + + +def test_none_of_multiple_values(dummy_form, dummy_field): + """ + the validator should work with multiple values like produced + by SelectMultiple fields + """ + dummy_field.data = ["d", "e"] + validator = NoneOf(["a", "b", "c"]) + validator(dummy_form, dummy_field) + + dummy_field.data = ["a", "e"] + validator = NoneOf(["a", "b", "c"]) + with pytest.raises(ValueError): + validator(dummy_form, dummy_field)