Skip to content

Commit

Permalink
Support Optional() inside the ForEach chain
Browse files Browse the repository at this point in the history
  • Loading branch information
jace committed Jun 21, 2019
1 parent a5368d0 commit 7df9d42
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
19 changes: 14 additions & 5 deletions baseframe/forms/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,29 @@ def is_empty(value):
return value not in _zero_values and not value


FakeField = namedtuple('FakeField', ['data', 'gettext', 'ngettext'])
FakeField = namedtuple('FakeField', ['data', 'raw_data', 'errors', 'gettext', 'ngettext'])


class ForEach(object):
"""
Runs specified validators on each element of an iterable value
Runs specified validators on each element of an iterable value. If a validator
raises :exc:`StopValidation`, it stops other validators within the chain given
to :class:`ForEach`, but not validators specified alongside.
"""
def __init__(self, validators):
self.validators = validators

def __call__(self, form, field):
for v in self.validators:
for element in field.data:
v(form, FakeField(element, field.gettext, field.ngettext))
for element in field.data:
fake_field = FakeField(element, element, [], field.gettext, field.ngettext)
for validator in self.validators:
try:
validator(form, fake_field)
except StopValidation as e:
if e.message:
raise
else:
break


class AllowedIf(object):
Expand Down
15 changes: 15 additions & 0 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,21 @@ def test_fails_blanklines(self):
assert self.form.validate() is False


class TestForEachChained(TestFormBase):
class Form(forms.Form):
textlist = forms.TextListField(
validators=[forms.ForEach([forms.Optional(), forms.URL()])]
)

def test_skips_blanklines_and_fails(self):
self.form.process(formdata=MultiDict({'textlist': "\r\nwww.example.com"}))
assert self.form.validate() is False

def test_skips_blanklines_and_passes(self):
self.form.process(formdata=MultiDict({'textlist': "\r\nhttp://www.example.com/"}))
assert self.form.validate() is True


class TestForEachFiltered(TestFormBase):
class Form(forms.Form):
textlist = forms.TextListField(
Expand Down

0 comments on commit 7df9d42

Please sign in to comment.