Skip to content
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
77 changes: 75 additions & 2 deletions voluptuous/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Replace, Range, Coerce, All, Any, Length, FqdnUrl, ALLOW_EXTRA, PREVENT_EXTRA,
validate, ExactSequence, Equal, Unordered, Number, Maybe, Datetime, Date,
Contains, Marker, IsDir, IsFile, PathExists, SomeOf, TooManyValid, Self,
raises, Union)
raises, Union, Clamp)
from voluptuous.humanize import humanize_error
from voluptuous.util import u, Capitalize, Lower, Strip, Title, Upper

Expand Down Expand Up @@ -585,7 +585,23 @@ def test_fix_157():
assert_raises(MultipleInvalid, s, ['four'])


def test_range_exlcudes_nan():
def test_range_inside():
s = Schema(Range(min=0, max=10))
assert_equal(5, s(5))


def test_range_outside():
s = Schema(Range(min=0, max=10))
assert_raises(MultipleInvalid, s, 12)
assert_raises(MultipleInvalid, s, -1)


def test_range_no_upper_limit():
s = Schema(Range(min=0))
assert_equal(123, s(123))


def test_range_excludes_nan():
s = Schema(Range(min=0, max=10))
assert_raises(MultipleInvalid, s, float('nan'))

Expand All @@ -595,6 +611,11 @@ def test_range_excludes_none():
assert_raises(MultipleInvalid, s, None)


def test_range_excludes_string():
s = Schema(Range(min=0, max=10))
assert_raises(MultipleInvalid, s, "abc")


def test_range_excludes_unordered_object():
class MyObject(object):
pass
Expand All @@ -603,6 +624,58 @@ class MyObject(object):
assert_raises(MultipleInvalid, s, MyObject())


def test_clamp_inside():
s = Schema(Clamp(min=1, max=10))
assert_equal(5, s(5))


def test_clamp_above():
s = Schema(Clamp(min=1, max=10))
assert_equal(10, s(12))


def test_clamp_below():
s = Schema(Clamp(min=1, max=10))
assert_equal(1, s(-3))


def test_clamp_invalid():
s = Schema(Clamp(min=1, max=10))
if sys.version_info.major >= 3:
assert_raises(MultipleInvalid, s, None)
assert_raises(MultipleInvalid, s, "abc")
else:
assert_equal(1, s(None))


def test_length_ok():
v1 = ['a', 'b', 'c']
s = Schema(Length(min=1, max=10))
assert_equal(v1, s(v1))
v2 = "abcde"
assert_equal(v2, s(v2))


def test_length_too_short():
v1 = []
s = Schema(Length(min=1, max=10))
assert_raises(MultipleInvalid, s, v1)
v2 = ''
assert_raises(MultipleInvalid, s, v2)


def test_length_too_long():
v = ['a', 'b', 'c']
s = Schema(Length(min=0, max=2))
assert_raises(MultipleInvalid, s, v)


def test_length_invalid():
v = None
s = Schema(Length(min=0, max=2))
assert_raises(MultipleInvalid, s, v)


def test_equal():
s = Schema(Equal(1))
s(1)
Expand Down
40 changes: 26 additions & 14 deletions voluptuous/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,10 +607,10 @@ def __call__(self, v):

return v

# Objects that lack a partial ordering, e.g. None will raise TypeError
# Objects that lack a partial ordering, e.g. None or strings will raise TypeError
except TypeError:
raise RangeInvalid(
self.msg or 'value must have a partial ordering')
self.msg or 'invalid value or type (must have a partial ordering)')

def __repr__(self):
return ('Range(min=%r, max=%r, min_included=%r,'
Expand Down Expand Up @@ -640,11 +640,17 @@ def __init__(self, min=None, max=None, msg=None):
self.msg = msg

def __call__(self, v):
if self.min is not None and v < self.min:
v = self.min
if self.max is not None and v > self.max:
v = self.max
return v
try:
if self.min is not None and v < self.min:
v = self.min
if self.max is not None and v > self.max:
v = self.max
return v

# Objects that lack a partial ordering, e.g. None or strings will raise TypeError
except TypeError:
raise RangeInvalid(
self.msg or 'invalid value or type (must have a partial ordering)')

def __repr__(self):
return 'Clamp(min=%s, max=%s)' % (self.min, self.max)
Expand All @@ -659,13 +665,19 @@ def __init__(self, min=None, max=None, msg=None):
self.msg = msg

def __call__(self, v):
if self.min is not None and len(v) < self.min:
raise LengthInvalid(
self.msg or 'length of value must be at least %s' % self.min)
if self.max is not None and len(v) > self.max:
raise LengthInvalid(
self.msg or 'length of value must be at most %s' % self.max)
return v
try:
if self.min is not None and len(v) < self.min:
raise LengthInvalid(
self.msg or 'length of value must be at least %s' % self.min)
if self.max is not None and len(v) > self.max:
raise LengthInvalid(
self.msg or 'length of value must be at most %s' % self.max)
return v

# Objects that havbe no length e.g. None or strings will raise TypeError
except TypeError:
raise RangeInvalid(
self.msg or 'invalid value or type')

def __repr__(self):
return 'Length(min=%s, max=%s)' % (self.min, self.max)
Expand Down