Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validators are checked to see if they are callable and not a class #410

Merged
merged 2 commits into from
Jun 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,20 @@ def test_required_flag(self):
form = self.F()
self.assertEqual(form.b(), u'<input id="b" name="b" required type="text" value="">')

def test_check_validators(self):
v1 = "Not callable"
v2 = validators.DataRequired

with self.assertRaisesRegexp(TypeError, "{} is not a valid validator because "
"it is not callable".format(v1)):
Field(validators=[v1])


with self.assertRaisesRegexp(TypeError, "{} is not a valid validator because "
"it is a class, it should be an "
"instance".format(v2)):
Field(validators=[v2])


class PrePostTestField(StringField):
def pre_validate(self, form):
Expand Down
23 changes: 22 additions & 1 deletion wtforms/fields/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import datetime
import decimal
import itertools
import inspect

from markupsafe import Markup, escape

Expand Down Expand Up @@ -104,7 +105,9 @@ def __init__(self, label=None, validators=None, filters=tuple(),
self.name = _prefix + _name
self.short_name = _name
self.type = type(self).__name__
self.validators = validators or list(self.validators)

self.check_validators(validators)
self.validators = validators or self.validators

self.id = id or self.name
self.label = Label(self.id, label if label is not None else self.gettext(_name.replace('_', ' ').title()))
Expand Down Expand Up @@ -154,6 +157,18 @@ def __call__(self, **kwargs):
"""
return self.meta.render_field(self, kwargs)

@classmethod
def check_validators(cls, validators):
if validators is not None:
for validator in validators:
if not callable(validator):
raise TypeError("{} is not a valid validator because it is not "
"callable".format(validator))

if inspect.isclass(validator):
raise TypeError("{} is not a valid validator because it is a class, "
"it should be an instance".format(validator))

def gettext(self, string):
"""
Get a translation for the given message.
Expand Down Expand Up @@ -190,6 +205,9 @@ def validate(self, form, extra_validators=tuple()):
self.errors = list(self.process_errors)
stop_validation = False

# Check the type of extra_validators
self.check_validators(extra_validators)

# Call pre_validate
try:
self.pre_validate(form)
Expand Down Expand Up @@ -340,6 +358,9 @@ def __init__(self, field_class, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.creation_counter = UnboundField.creation_counter
validators = kwargs.get('validators')
if validators:
self.field_class.check_validators(validators)

def bind(self, form, name, prefix='', translations=None, **kwargs):
kw = dict(
Expand Down