Hello,

As talked with Chris McDonough at #freenode, here is the patch for
adding Regex and Email validators to Colander.
He has already implemented the Function validator as discussed.

Thanks!
--
Steve Howe
howest...@googlemail.com
Index: __init__.py
===================================================================
--- __init__.py	(revision 8854)
+++ __init__.py	(working copy)
@@ -2,6 +2,7 @@
 import itertools
 import iso8601
 import pprint
+import re
 
 class _missing(object):
     pass
@@ -170,6 +171,37 @@
         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 +246,6 @@
                     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 """
Index: tests.py
===================================================================
--- tests.py	(revision 8854)
+++ tests.py	(working copy)
@@ -194,6 +194,47 @@
         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, 'm...@here.com'), None)
+        self.assertEqual(validator(None, 'm...@here1.com'), None)
+        self.assertEqual(validator(None, 'n...@here1.us'), None)
+        self.assertEqual(validator(None, 'n...@here1.info'), 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, 'm...@here.')
+        self.assertRaises(Invalid, validator, None, 'n...@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
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to