- Add Email and Regex validators.

This commit is contained in:
Chris McDonough
2010-04-05 05:50:04 +00:00
parent cb8b9d0c91
commit 68d49269c6
4 changed files with 82 additions and 1 deletions

View File

@@ -4,6 +4,8 @@ Changes
Next release
------------
- Add Email and Regex validators.
- Raise a ``colander.Invalid`` error if a ``colander.SequenceSchema``
is created with more than one member.

View File

@@ -2,6 +2,7 @@ import datetime
import itertools
import iso8601
import pprint
import re
class _missing(object):
pass
@@ -170,6 +171,39 @@ class Function(object):
if isinstance(result, basestring):
raise Invalid(node, result)
class Regex(object):
""" Regular expression validator. Initialize it with the string
regular expression ``regex`` that will be compiled and matched
against ``value`` when validator is called. If ``msg`` is
supplied, it will be the error message to be used; otherwise,
defaults to 'String does not match expected pattern'.
When calling, if ``value`` matches the regular expression,
validation succeeds; otherwise, :exc:`colander.Invalid` is
raised with the ``msg`` error message.
"""
def __init__(self, regex, msg=None):
self.match_object = re.compile(regex)
if msg is None:
self.msg = "String does not match expected pattern"
else:
self.msg = msg
def __call__(self, node, value):
if self.match_object.match(value) is None:
raise Invalid(self.msg)
class Email(Regex):
""" Email address validator. If ``msg`` is supplied, it will be
the error message to be used when raising :exc:`colander.Invalid`;
otherwise, defaults to "Invalid email address".
"""
def __init__(self, msg=None):
if msg is None:
msg = "Invalid email address"
super(Email, self).__init__(
u'(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$', msg=msg)
class Range(object):
""" Validator which succeeds if the value it is passed is greater
or equal to ``min`` and less than or equal to ``max``. If ``min``
@@ -214,7 +248,6 @@ class Length(object):
node,
'Longer than maximum length %s' % self.max)
class OneOf(object):
""" Validator which succeeds if the value passed to it is one of
a fixed set of values """

View File

@@ -194,6 +194,48 @@ class TestRange(unittest.TestCase):
e = invalid_exc(validator, None, 2)
self.assertEqual(e.msg, '2 is greater than maximum value 1')
class TestRegex(unittest.TestCase):
def _makeOne(self, pattern):
from colander import Regex
return Regex(pattern)
def test_valid_regex(self):
self.assertEqual(self._makeOne('a')(None, 'a'), None)
self.assertEqual(self._makeOne('[0-9]+')(None, '1111'), None)
self.assertEqual(self._makeOne('')(None, ''), None)
self.assertEqual(self._makeOne('.*')(None, ''), None)
def test_invalid_regexs(self):
from colander import Invalid
self.assertRaises(Invalid, self._makeOne('[0-9]+'), None, 'a')
self.assertRaises(Invalid, self._makeOne('a{2,4}'), None, 'ba')
class TestEmail(unittest.TestCase):
def _makeOne(self):
from colander import Email
return Email()
def test_valid_emails(self):
validator = self._makeOne()
self.assertEqual(validator(None, 'me@here.com'), None)
self.assertEqual(validator(None, 'me1@here1.com'), None)
self.assertEqual(validator(None, 'name@here1.us'), None)
self.assertEqual(validator(None, 'name@here1.info'), None)
self.assertEqual(validator(None, 'foo@bar.baz.biz'), None)
def test_empty_email(self):
validator = self._makeOne()
from colander import Invalid
self.assertRaises(Invalid, validator, None, '')
def test_invalid_emails(self):
validator = self._makeOne()
from colander import Invalid
self.assertRaises(Invalid, validator, None, 'me@here.')
self.assertRaises(Invalid, validator, None, 'name@here.comcom')
self.assertRaises(Invalid, validator, None, '@here.us')
self.assertRaises(Invalid, validator, None, '(name)@here.info')
class TestLength(unittest.TestCase):
def _makeOne(self, min=None, max=None):
from colander import Length

View File

@@ -22,6 +22,10 @@ Validators
.. autoclass:: Function
.. autoclass:: Regex
.. autoclass:: Email
Types
~~~~~