- Add `colander.ContainsOnly
and
colander.url
` validators.
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
Next release
|
||||||
|
------------
|
||||||
|
|
||||||
|
Features
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
- Add ``colander.ContainsOnly`` and ``colander.url`` validators.
|
||||||
|
|
||||||
1.0a1 (2013-01-10)
|
1.0a1 (2013-01-10)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import time
|
import time
|
||||||
@@ -356,6 +358,24 @@ class OneOf(object):
|
|||||||
mapping={'val':value, 'choices':choices})
|
mapping={'val':value, 'choices':choices})
|
||||||
raise Invalid(node, err)
|
raise Invalid(node, err)
|
||||||
|
|
||||||
|
class ContainsOnly(object):
|
||||||
|
""" Validator which succeeds if the value passed to is a sequence and each
|
||||||
|
element in the sequence is also in the sequence passed as ``acceptable``
|
||||||
|
"""
|
||||||
|
err_template = _(
|
||||||
|
'One or more of the choices you made was not acceptable'
|
||||||
|
)
|
||||||
|
def __init__(self, acceptable):
|
||||||
|
self.acceptable = set(acceptable)
|
||||||
|
|
||||||
|
def __call__(self, node, value):
|
||||||
|
if not set(value).issubset(self.acceptable):
|
||||||
|
err = _(
|
||||||
|
self.err_template,
|
||||||
|
mapping = {'val':value, 'acceptable':self.acceptable}
|
||||||
|
)
|
||||||
|
raise Invalid(node, err)
|
||||||
|
|
||||||
def luhnok(node, value):
|
def luhnok(node, value):
|
||||||
""" Validator which checks to make sure that the value passes a luhn
|
""" Validator which checks to make sure that the value passes a luhn
|
||||||
mod-10 checksum (credit cards). ``value`` must be a string, not an
|
mod-10 checksum (credit cards). ``value`` must be a string, not an
|
||||||
@@ -386,6 +406,10 @@ def _luhnok(value):
|
|||||||
sum = sum + digit
|
sum = sum + digit
|
||||||
return sum
|
return sum
|
||||||
|
|
||||||
|
URL_REGEX = r"""(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""" # "emacs!
|
||||||
|
|
||||||
|
url = Regex(URL_REGEX, _('Must be a URL'))
|
||||||
|
|
||||||
class SchemaType(object):
|
class SchemaType(object):
|
||||||
""" Base class for all schema types """
|
""" Base class for all schema types """
|
||||||
def flatten(self, node, appstruct, prefix='', listitem=False):
|
def flatten(self, node, appstruct, prefix='', listitem=False):
|
||||||
|
@@ -408,6 +408,30 @@ class TestOneOf(unittest.TestCase):
|
|||||||
e = invalid_exc(validator, None, None)
|
e = invalid_exc(validator, None, None)
|
||||||
self.assertEqual(e.msg.interpolate(), '"None" is not one of 1, 2')
|
self.assertEqual(e.msg.interpolate(), '"None" is not one of 1, 2')
|
||||||
|
|
||||||
|
class TestContainsOnly(unittest.TestCase):
|
||||||
|
def _makeOne(self, values):
|
||||||
|
from colander import ContainsOnly
|
||||||
|
return ContainsOnly(values)
|
||||||
|
|
||||||
|
def test_success(self):
|
||||||
|
validator = self._makeOne([1])
|
||||||
|
self.assertEqual(validator(None, [1]), None)
|
||||||
|
|
||||||
|
def test_failure(self):
|
||||||
|
validator = self._makeOne([1])
|
||||||
|
e = invalid_exc(validator, None, [2])
|
||||||
|
self.assertEqual(
|
||||||
|
e.msg.interpolate(),
|
||||||
|
'One or more of the choices you made was not acceptable'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_failure_with_custom_error_template(self):
|
||||||
|
validator = self._makeOne([1])
|
||||||
|
from colander import _
|
||||||
|
validator.err_template = _('${val}: ${acceptable}')
|
||||||
|
e = invalid_exc(validator, None, [2])
|
||||||
|
self.assertTrue('[2]' in e.msg.interpolate())
|
||||||
|
|
||||||
class Test_luhnok(unittest.TestCase):
|
class Test_luhnok(unittest.TestCase):
|
||||||
def _callFUT(self, node, value):
|
def _callFUT(self, node, value):
|
||||||
from colander import luhnok
|
from colander import luhnok
|
||||||
@@ -432,6 +456,21 @@ class Test_luhnok(unittest.TestCase):
|
|||||||
val = '4111111111111111'
|
val = '4111111111111111'
|
||||||
self.assertFalse(self._callFUT(None, val))
|
self.assertFalse(self._callFUT(None, val))
|
||||||
|
|
||||||
|
class Test_url_validator(unittest.TestCase):
|
||||||
|
def _callFUT(self, val):
|
||||||
|
from colander import url
|
||||||
|
return url(None, val)
|
||||||
|
|
||||||
|
def test_it_success(self):
|
||||||
|
val = 'http://example.com'
|
||||||
|
result = self._callFUT(val)
|
||||||
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
|
def test_it_failure(self):
|
||||||
|
val = 'not-a-url'
|
||||||
|
from colander import Invalid
|
||||||
|
self.assertRaises(Invalid, self._callFUT, val)
|
||||||
|
|
||||||
class TestSchemaType(unittest.TestCase):
|
class TestSchemaType(unittest.TestCase):
|
||||||
def _makeOne(self, *arg, **kw):
|
def _makeOne(self, *arg, **kw):
|
||||||
from colander import SchemaType
|
from colander import SchemaType
|
||||||
|
@@ -59,6 +59,8 @@ Validators
|
|||||||
|
|
||||||
.. autoclass:: OneOf
|
.. autoclass:: OneOf
|
||||||
|
|
||||||
|
.. autoclass:: ContainsOnly
|
||||||
|
|
||||||
.. autoclass:: Function
|
.. autoclass:: Function
|
||||||
|
|
||||||
.. autoclass:: Regex
|
.. autoclass:: Regex
|
||||||
@@ -67,6 +69,10 @@ Validators
|
|||||||
|
|
||||||
.. autofunction:: luhnok
|
.. autofunction:: luhnok
|
||||||
|
|
||||||
|
.. attribute:: url
|
||||||
|
|
||||||
|
A validator which ensures the value is a URL (via regex).
|
||||||
|
|
||||||
Types
|
Types
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user