diff --git a/gluon/validators.py b/gluon/validators.py index d5859afa..8b3d57ea 100644 --- a/gluon/validators.py +++ b/gluon/validators.py @@ -32,6 +32,7 @@ except ImportError: JSONErrors += (JSONDecodeError,) __all__ = [ + 'ANY_OF', 'CLEANUP', 'CRYPT', 'IS_ALPHANUMERIC', @@ -2591,6 +2592,38 @@ class IS_SLUG(Validator): return (urlify(value, self.maxlen, self.keep_underscores), None) +class ANY_OF(Validator): + """ + test if any of the validators in a list return successfully + + >>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('a@b.co') + ('a@b.co', None) + >>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('abco') + ('abco', None) + >>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('@ab.co') + ('@ab.co', 'enter only letters, numbers, and underscore') + >>> ANY_OF([IS_ALPHANUMERIC(),IS_EMAIL()])('@ab.co') + ('@ab.co', 'enter a valid email address') + """ + + def __init__(self, subs): + self.subs = subs + + def __call__(self, value): + for validator in self.subs: + value, error = validator(value) + if error == None: + break + return value, error + + def formatter(self, value): + # Use the formatter of the first subvalidator + # that validates the value and has a formatter + for validator in self.subs: + if hasattr(validator, 'formatter') and validator(value)[1] != None: + return validator.formatter(value) + + class IS_EMPTY_OR(Validator): """ dummy class for testing IS_EMPTY_OR