|
0 |
import collections
|
0 | 1 |
import copy
|
1 | |
import collections
|
2 | |
from enum import Enum
|
|
2 |
|
|
3 |
try:
|
|
4 |
from enum import Enum
|
|
5 |
except ImportError:
|
|
6 |
Enum = None
|
3 | 7 |
import os
|
4 | 8 |
import sys
|
5 | 9 |
|
6 | |
from nose.tools import assert_equal, assert_false, assert_raises, assert_true
|
7 | |
|
8 | |
from voluptuous import (
|
9 | |
Schema, Required, Exclusive, Inclusive, Optional, Extra, Invalid, In, Remove,
|
10 | |
Literal, Url, MultipleInvalid, LiteralInvalid, TypeInvalid, NotIn, Match, Email,
|
11 | |
Replace, Range, Coerce, All, Any, Length, FqdnUrl, ALLOW_EXTRA, PREVENT_EXTRA,
|
12 | |
validate, ExactSequence, Equal, Unordered, Number, Maybe, Datetime, Date,
|
13 | |
Contains, Marker, IsDir, IsFile, PathExists, SomeOf, TooManyValid, Self,
|
14 | |
raises, Union, Clamp)
|
|
10 |
import pytest
|
|
11 |
from voluptuous import (ALLOW_EXTRA, PREVENT_EXTRA, All, Any, Clamp, Coerce,
|
|
12 |
Contains, Date, Datetime, Email, Equal, ExactSequence,
|
|
13 |
Exclusive, Extra, FqdnUrl, In, Inclusive, Invalid,
|
|
14 |
IsDir, IsFile, Length, Literal, LiteralInvalid, Marker,
|
|
15 |
Match, Maybe, MultipleInvalid, NotIn, Number, Object,
|
|
16 |
Optional, PathExists, Range, Remove, Replace, Required,
|
|
17 |
Schema, Self, SomeOf, TooManyValid, TypeInvalid, Union,
|
|
18 |
Unordered, Url, raises, validate)
|
15 | 19 |
from voluptuous.humanize import humanize_error
|
16 | |
from voluptuous.util import u, Capitalize, Lower, Strip, Title, Upper
|
|
20 |
from voluptuous.util import Capitalize, Lower, Strip, Title, Upper, u
|
17 | 21 |
|
18 | 22 |
|
19 | 23 |
def test_new_required_test():
|
20 | 24 |
schema = Schema({
|
21 | 25 |
'my_key': All(int, Range(1, 20)),
|
22 | 26 |
}, required=True)
|
23 | |
assert_true(schema.required)
|
|
27 |
assert schema.required
|
24 | 28 |
|
25 | 29 |
|
26 | 30 |
def test_exact_sequence():
|
|
31 | 35 |
assert True
|
32 | 36 |
else:
|
33 | 37 |
assert False, "Did not raise Invalid"
|
34 | |
assert_equal(schema([1, 2]), [1, 2])
|
|
38 |
assert schema([1, 2]) == [1, 2]
|
35 | 39 |
|
36 | 40 |
|
37 | 41 |
def test_required():
|
|
41 | 45 |
try:
|
42 | 46 |
schema({})
|
43 | 47 |
except Invalid as e:
|
44 | |
assert_equal(str(e), "required key not provided @ data['q']")
|
|
48 |
assert str(e) == "required key not provided @ data['q']"
|
45 | 49 |
else:
|
46 | 50 |
assert False, "Did not raise Invalid"
|
47 | 51 |
|
|
50 | 54 |
"""Verify that Required does not break Extra."""
|
51 | 55 |
schema = Schema({Required('toaster'): str, Extra: object})
|
52 | 56 |
r = schema({'toaster': 'blue', 'another_valid_key': 'another_valid_value'})
|
53 | |
assert_equal(
|
54 | |
r, {'toaster': 'blue', 'another_valid_key': 'another_valid_value'})
|
|
57 |
assert r == {'toaster': 'blue', 'another_valid_key': 'another_valid_value'}
|
55 | 58 |
|
56 | 59 |
|
57 | 60 |
def test_iterate_candidates():
|
|
62 | 65 |
}
|
63 | 66 |
# toaster should be first.
|
64 | 67 |
from voluptuous.schema_builder import _iterate_mapping_candidates
|
65 | |
assert_equal(_iterate_mapping_candidates(schema)[0][0], 'toaster')
|
|
68 |
assert _iterate_mapping_candidates(schema)[0][0] == 'toaster'
|
66 | 69 |
|
67 | 70 |
|
68 | 71 |
def test_in():
|
|
72 | 75 |
try:
|
73 | 76 |
schema({"color": "orange"})
|
74 | 77 |
except Invalid as e:
|
75 | |
assert_equal(str(e), "value must be one of ['blue', 'red', 'yellow'] for dictionary value @ data['color']")
|
|
78 |
assert str(e) == "value must be one of ['blue', 'red', 'yellow'] for dictionary value @ data['color']"
|
76 | 79 |
else:
|
77 | 80 |
assert False, "Did not raise InInvalid"
|
78 | 81 |
|
|
84 | 87 |
try:
|
85 | 88 |
schema({"color": "blue"})
|
86 | 89 |
except Invalid as e:
|
87 | |
assert_equal(str(e), "value must not be one of ['blue', 'red', 'yellow'] for dictionary value @ data['color']")
|
|
90 |
assert str(e) == "value must not be one of ['blue', 'red', 'yellow'] for dictionary value @ data['color']"
|
88 | 91 |
else:
|
89 | 92 |
assert False, "Did not raise NotInInvalid"
|
90 | 93 |
|
|
96 | 99 |
try:
|
97 | 100 |
schema({'color': ['blue', 'yellow']})
|
98 | 101 |
except Invalid as e:
|
99 | |
assert_equal(str(e),
|
100 | |
"value is not allowed for dictionary value @ data['color']")
|
|
102 |
assert str(e) == "value is not allowed for dictionary value @ data['color']"
|
101 | 103 |
|
102 | 104 |
|
103 | 105 |
def test_remove():
|
|
112 | 114 |
# remove keys by type
|
113 | 115 |
schema = Schema({"weight": float,
|
114 | 116 |
"amount": int,
|
115 | |
# remvove str keys with int values
|
|
117 |
# remove str keys with int values
|
116 | 118 |
Remove(str): int,
|
117 | 119 |
# keep str keys with str values
|
118 | 120 |
str: str})
|
|
129 | 131 |
# remove value from list
|
130 | 132 |
schema = Schema([Remove(1), int])
|
131 | 133 |
out_ = schema([1, 2, 3, 4, 1, 5, 6, 1, 1, 1])
|
132 | |
assert_equal(out_, [2, 3, 4, 5, 6])
|
|
134 |
assert out_ == [2, 3, 4, 5, 6]
|
133 | 135 |
|
134 | 136 |
# remove values from list by type
|
135 | 137 |
schema = Schema([1.0, Remove(float), int])
|
136 | 138 |
out_ = schema([1, 2, 1.0, 2.0, 3.0, 4])
|
137 | |
assert_equal(out_, [1, 2, 1.0, 4])
|
|
139 |
assert out_ == [1, 2, 1.0, 4]
|
138 | 140 |
|
139 | 141 |
|
140 | 142 |
def test_extra_empty_errors():
|
|
153 | 155 |
try:
|
154 | 156 |
schema([{"c": 1}])
|
155 | 157 |
except Invalid as e:
|
156 | |
assert_equal(str(e), "{'c': 1} not match for {'b': 1} @ data[0]")
|
|
158 |
assert str(e) == "{'c': 1} not match for {'b': 1} @ data[0]"
|
157 | 159 |
else:
|
158 | 160 |
assert False, "Did not raise Invalid"
|
159 | 161 |
|
|
161 | 163 |
try:
|
162 | 164 |
schema({"b": 1})
|
163 | 165 |
except MultipleInvalid as e:
|
164 | |
assert_equal(str(e), "{'b': 1} not match for {'a': 1}")
|
165 | |
assert_equal(len(e.errors), 1)
|
166 | |
assert_equal(type(e.errors[0]), LiteralInvalid)
|
|
166 |
assert str(e) == "{'b': 1} not match for {'a': 1}"
|
|
167 |
assert len(e.errors) == 1
|
|
168 |
assert type(e.errors[0]) == LiteralInvalid
|
167 | 169 |
else:
|
168 | 170 |
assert False, "Did not raise Invalid"
|
169 | 171 |
|
|
178 | 180 |
try:
|
179 | 181 |
schema(None)
|
180 | 182 |
except MultipleInvalid as e:
|
181 | |
assert_equal(str(e), "expected C1")
|
182 | |
assert_equal(len(e.errors), 1)
|
183 | |
assert_equal(type(e.errors[0]), TypeInvalid)
|
|
183 |
assert str(e) == "expected C1"
|
|
184 |
assert len(e.errors) == 1
|
|
185 |
assert type(e.errors[0]) == TypeInvalid
|
184 | 186 |
else:
|
185 | 187 |
assert False, "Did not raise Invalid"
|
186 | 188 |
|
|
194 | 196 |
try:
|
195 | 197 |
schema(None)
|
196 | 198 |
except MultipleInvalid as e:
|
197 | |
assert_equal(str(e), "expected C2")
|
198 | |
assert_equal(len(e.errors), 1)
|
199 | |
assert_equal(type(e.errors[0]), TypeInvalid)
|
|
199 |
assert str(e) == "expected C2"
|
|
200 |
assert len(e.errors) == 1
|
|
201 |
assert type(e.errors[0]) == TypeInvalid
|
200 | 202 |
else:
|
201 | 203 |
assert False, "Did not raise Invalid"
|
202 | 204 |
|
|
215 | 217 |
try:
|
216 | 218 |
schema({"email": None})
|
217 | 219 |
except MultipleInvalid as e:
|
218 | |
assert_equal(str(e),
|
219 | |
"expected an email address for dictionary value @ data['email']")
|
|
220 |
assert str(e) == "expected an email address for dictionary value @ data['email']"
|
220 | 221 |
else:
|
221 | 222 |
assert False, "Did not raise Invalid for None URL"
|
222 | 223 |
|
|
227 | 228 |
try:
|
228 | 229 |
schema({"email": ''})
|
229 | 230 |
except MultipleInvalid as e:
|
230 | |
assert_equal(str(e),
|
231 | |
"expected an email address for dictionary value @ data['email']")
|
|
231 |
assert str(e) == "expected an email address for dictionary value @ data['email']"
|
232 | 232 |
else:
|
233 | 233 |
assert False, "Did not raise Invalid for empty string URL"
|
234 | 234 |
|
|
239 | 239 |
try:
|
240 | 240 |
schema({"email": 'a@.com'})
|
241 | 241 |
except MultipleInvalid as e:
|
242 | |
assert_equal(str(e),
|
243 | |
"expected an email address for dictionary value @ data['email']")
|
|
242 |
assert str(e) == "expected an email address for dictionary value @ data['email']"
|
244 | 243 |
else:
|
245 | 244 |
assert False, "Did not raise Invalid for empty string URL"
|
|
245 |
|
246 | 246 |
|
247 | 247 |
def test_email_validation_with_bad_data():
|
248 | 248 |
""" Test with bad data in email address """
|
|
251 | 251 |
try:
|
252 | 252 |
schema({"email": 'john@voluptuous.com>'})
|
253 | 253 |
except MultipleInvalid as e:
|
254 | |
assert_equal(str(e),
|
255 | |
"expected an email address for dictionary value @ data['email']")
|
|
254 |
assert str(e) == "expected an email address for dictionary value @ data['email']"
|
256 | 255 |
else:
|
257 | 256 |
assert False, "Did not raise Invalid for bad email " + email
|
258 | 257 |
|
|
271 | 270 |
try:
|
272 | 271 |
schema({"url": "http://localhost/"})
|
273 | 272 |
except MultipleInvalid as e:
|
274 | |
assert_equal(str(e),
|
275 | |
"expected a fully qualified domain name URL for dictionary value @ data['url']")
|
|
273 |
assert str(e) == "expected a fully qualified domain name URL for dictionary value @ data['url']"
|
276 | 274 |
else:
|
277 | 275 |
assert False, "Did not raise Invalid for None URL"
|
278 | 276 |
|
|
283 | 281 |
try:
|
284 | 282 |
schema({"url": None})
|
285 | 283 |
except MultipleInvalid as e:
|
286 | |
assert_equal(str(e),
|
287 | |
"expected a fully qualified domain name URL for dictionary value @ data['url']")
|
|
284 |
assert str(e) == "expected a fully qualified domain name URL for dictionary value @ data['url']"
|
288 | 285 |
else:
|
289 | 286 |
assert False, "Did not raise Invalid for None URL"
|
290 | 287 |
|
|
295 | 292 |
try:
|
296 | 293 |
schema({"url": ''})
|
297 | 294 |
except MultipleInvalid as e:
|
298 | |
assert_equal(str(e),
|
299 | |
"expected a fully qualified domain name URL for dictionary value @ data['url']")
|
|
295 |
assert str(e) == "expected a fully qualified domain name URL for dictionary value @ data['url']"
|
300 | 296 |
else:
|
301 | 297 |
assert False, "Did not raise Invalid for empty string URL"
|
302 | 298 |
|
|
307 | 303 |
try:
|
308 | 304 |
schema({"url": 'http://'})
|
309 | 305 |
except MultipleInvalid as e:
|
310 | |
assert_equal(str(e),
|
311 | |
"expected a fully qualified domain name URL for dictionary value @ data['url']")
|
|
306 |
assert str(e) == "expected a fully qualified domain name URL for dictionary value @ data['url']"
|
312 | 307 |
else:
|
313 | 308 |
assert False, "Did not raise Invalid for empty string URL"
|
314 | 309 |
|
|
327 | 322 |
try:
|
328 | 323 |
schema({"url": None})
|
329 | 324 |
except MultipleInvalid as e:
|
330 | |
assert_equal(str(e),
|
331 | |
"expected a URL for dictionary value @ data['url']")
|
|
325 |
assert str(e) == "expected a URL for dictionary value @ data['url']"
|
332 | 326 |
else:
|
333 | 327 |
assert False, "Did not raise Invalid for None URL"
|
334 | 328 |
|
|
339 | 333 |
try:
|
340 | 334 |
schema({"url": ''})
|
341 | 335 |
except MultipleInvalid as e:
|
342 | |
assert_equal(str(e),
|
343 | |
"expected a URL for dictionary value @ data['url']")
|
|
336 |
assert str(e) == "expected a URL for dictionary value @ data['url']"
|
344 | 337 |
else:
|
345 | 338 |
assert False, "Did not raise Invalid for empty string URL"
|
346 | 339 |
|
|
351 | 344 |
try:
|
352 | 345 |
schema({"url": 'http://'})
|
353 | 346 |
except MultipleInvalid as e:
|
354 | |
assert_equal(str(e),
|
355 | |
"expected a URL for dictionary value @ data['url']")
|
|
347 |
assert str(e) == "expected a URL for dictionary value @ data['url']"
|
356 | 348 |
else:
|
357 | 349 |
assert False, "Did not raise Invalid for empty string URL"
|
358 | 350 |
|
|
416 | 408 |
extension = {Required('a'): int}
|
417 | 409 |
extended = base.extend(extension)
|
418 | 410 |
|
419 | |
assert_equal(len(base.schema), 1)
|
420 | |
assert_true(isinstance(list(base.schema)[0], Optional))
|
421 | |
assert_equal(len(extended.schema), 1)
|
422 | |
assert_true((list(extended.schema)[0], Required))
|
|
411 |
assert len(base.schema) == 1
|
|
412 |
assert isinstance(list(base.schema)[0], Optional)
|
|
413 |
assert len(extended.schema) == 1
|
|
414 |
assert list(extended.schema)[0]
|
423 | 415 |
|
424 | 416 |
|
425 | 417 |
def test_subschema_extension():
|
|
428 | 420 |
extension = {'d': str, 'a': {'b': str, 'e': int}}
|
429 | 421 |
extended = base.extend(extension)
|
430 | 422 |
|
431 | |
assert_equal(base.schema, {'a': {'b': int, 'c': float}})
|
432 | |
assert_equal(extension, {'d': str, 'a': {'b': str, 'e': int}})
|
433 | |
assert_equal(extended.schema, {'a': {'b': str, 'c': float, 'e': int}, 'd': str})
|
|
423 |
assert base.schema == {'a': {'b': int, 'c': float}}
|
|
424 |
assert extension == {'d': str, 'a': {'b': str, 'e': int}}
|
|
425 |
assert extended.schema == {'a': {'b': str, 'c': float, 'e': int}, 'd': str}
|
434 | 426 |
|
435 | 427 |
|
436 | 428 |
def test_schema_extend_handles_schema_subclass():
|
|
448 | 440 |
|
449 | 441 |
|
450 | 442 |
def test_equality():
|
451 | |
assert_equal(Schema('foo'), Schema('foo'))
|
452 | |
|
453 | |
assert_equal(Schema(['foo', 'bar', 'baz']),
|
454 | |
Schema(['foo', 'bar', 'baz']))
|
|
443 |
assert Schema('foo') == Schema('foo')
|
|
444 |
|
|
445 |
assert Schema(['foo', 'bar', 'baz']) == Schema(['foo', 'bar', 'baz'])
|
455 | 446 |
|
456 | 447 |
# Ensure two Schemas w/ two equivalent dicts initialized in a different
|
457 | 448 |
# order are considered equal.
|
|
465 | 456 |
dict_b['bar'] = 2
|
466 | 457 |
dict_b['foo'] = 1
|
467 | 458 |
|
468 | |
assert_equal(Schema(dict_a), Schema(dict_b))
|
|
459 |
assert Schema(dict_a) == Schema(dict_b)
|
469 | 460 |
|
470 | 461 |
|
471 | 462 |
def test_equality_negative():
|
472 | 463 |
"""Verify that Schema objects are not equal to string representations"""
|
473 | |
assert_false(Schema('foo') == 'foo')
|
474 | |
|
475 | |
assert_false(Schema(['foo', 'bar']) == "['foo', 'bar']")
|
476 | |
assert_false(Schema(['foo', 'bar']) == Schema("['foo', 'bar']"))
|
477 | |
|
478 | |
assert_false(Schema({'foo': 1, 'bar': 2}) == "{'foo': 1, 'bar': 2}")
|
479 | |
assert_false(Schema({'foo': 1, 'bar': 2}) == Schema("{'foo': 1, 'bar': 2}"))
|
|
464 |
assert not Schema('foo') == 'foo'
|
|
465 |
|
|
466 |
assert not Schema(['foo', 'bar']) == "['foo', 'bar']"
|
|
467 |
assert not Schema(['foo', 'bar']) == Schema("['foo', 'bar']")
|
|
468 |
|
|
469 |
assert not Schema({'foo': 1, 'bar': 2}) == "{'foo': 1, 'bar': 2}"
|
|
470 |
assert not Schema({'foo': 1, 'bar': 2}) == Schema("{'foo': 1, 'bar': 2}")
|
480 | 471 |
|
481 | 472 |
|
482 | 473 |
def test_inequality():
|
483 | |
assert_true(Schema('foo') != 'foo')
|
484 | |
|
485 | |
assert_true(Schema(['foo', 'bar']) != "['foo', 'bar']")
|
486 | |
assert_true(Schema(['foo', 'bar']) != Schema("['foo', 'bar']"))
|
487 | |
|
488 | |
assert_true(Schema({'foo': 1, 'bar': 2}) != "{'foo': 1, 'bar': 2}")
|
489 | |
assert_true(Schema({'foo': 1, 'bar': 2}) != Schema("{'foo': 1, 'bar': 2}"))
|
|
474 |
assert Schema('foo') != 'foo'
|
|
475 |
|
|
476 |
assert Schema(['foo', 'bar']) != "['foo', 'bar']"
|
|
477 |
assert Schema(['foo', 'bar']) != Schema("['foo', 'bar']")
|
|
478 |
|
|
479 |
assert Schema({'foo': 1, 'bar': 2}) != "{'foo': 1, 'bar': 2}"
|
|
480 |
assert Schema({'foo': 1, 'bar': 2}) != Schema("{'foo': 1, 'bar': 2}")
|
490 | 481 |
|
491 | 482 |
|
492 | 483 |
def test_inequality_negative():
|
493 | |
assert_false(Schema('foo') != Schema('foo'))
|
494 | |
|
495 | |
assert_false(Schema(['foo', 'bar', 'baz']) !=
|
496 | |
Schema(['foo', 'bar', 'baz']))
|
|
484 |
assert not Schema('foo') != Schema('foo')
|
|
485 |
|
|
486 |
assert not Schema(['foo', 'bar', 'baz']) != Schema(['foo', 'bar', 'baz'])
|
497 | 487 |
|
498 | 488 |
# Ensure two Schemas w/ two equivalent dicts initialized in a different
|
499 | 489 |
# order are considered equal.
|
|
507 | 497 |
dict_b['bar'] = 2
|
508 | 498 |
dict_b['foo'] = 1
|
509 | 499 |
|
510 | |
assert_false(Schema(dict_a) != Schema(dict_b))
|
|
500 |
assert not Schema(dict_a) != Schema(dict_b)
|
511 | 501 |
|
512 | 502 |
|
513 | 503 |
def test_repr():
|
|
520 | 510 |
all_ = All('10', Coerce(int), msg='all msg')
|
521 | 511 |
maybe_int = Maybe(int)
|
522 | 512 |
|
523 | |
assert_equal(repr(match), "Match('a pattern', msg='message')")
|
524 | |
assert_equal(repr(replace), "Replace('you', 'I', msg='you and I')")
|
525 | |
assert_equal(
|
526 | |
repr(range_),
|
527 | |
"Range(min=0, max=42, min_included=False, max_included=False, msg='number not in range')"
|
528 | |
)
|
529 | |
assert_equal(repr(coerce_), "Coerce(int, msg='moo')")
|
530 | |
assert_equal(repr(all_), "All('10', Coerce(int, msg=None), msg='all msg')")
|
531 | |
assert_equal(repr(maybe_int), "Any(None, %s, msg=None)" % str(int))
|
|
513 |
assert repr(match) == "Match('a pattern', msg='message')"
|
|
514 |
assert repr(replace) == "Replace('you', 'I', msg='you and I')"
|
|
515 |
assert repr(range_) == "Range(min=0, max=42, min_included=False, max_included=False, msg='number not in range')"
|
|
516 |
assert repr(coerce_) == "Coerce(int, msg='moo')"
|
|
517 |
assert repr(all_) == "All('10', Coerce(int, msg=None), msg='all msg')"
|
|
518 |
assert repr(maybe_int) == "Any(None, %s, msg=None)" % str(int)
|
532 | 519 |
|
533 | 520 |
|
534 | 521 |
def test_list_validation_messages():
|
|
544 | 531 |
try:
|
545 | 532 |
schema(dict(even_numbers=[3]))
|
546 | 533 |
except Invalid as e:
|
547 | |
assert_equal(len(e.errors), 1, e.errors)
|
548 | |
assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]")
|
549 | |
assert_equal(str(e), "3 is not even @ data['even_numbers'][0]")
|
|
534 |
assert len(e.errors) == 1
|
|
535 |
assert str(e.errors[0]) == "3 is not even @ data['even_numbers'][0]"
|
|
536 |
assert str(e) == "3 is not even @ data['even_numbers'][0]"
|
550 | 537 |
else:
|
551 | 538 |
assert False, "Did not raise Invalid"
|
552 | 539 |
|
|
565 | 552 |
try:
|
566 | 553 |
schema(dict(even_numbers=[3]))
|
567 | 554 |
except Invalid as e:
|
568 | |
assert_equal(len(e.errors), 1, e.errors)
|
569 | |
assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]")
|
570 | |
assert_equal(str(e), "3 is not even @ data['even_numbers'][0]")
|
|
555 |
assert len(e.errors) == 1
|
|
556 |
assert str(e.errors[0]) == "3 is not even @ data['even_numbers'][0]"
|
|
557 |
assert str(e) == "3 is not even @ data['even_numbers'][0]"
|
571 | 558 |
else:
|
572 | 559 |
assert False, "Did not raise Invalid"
|
573 | 560 |
|
|
584 | 571 |
try:
|
585 | 572 |
schema(data)
|
586 | 573 |
except MultipleInvalid as e:
|
587 | |
assert_equal(
|
588 | |
humanize_error(data, e),
|
589 | |
"expected int for dictionary value @ data['a']. Got 'not an int'\n"
|
590 | |
"expected str @ data['b'][0]. Got 123"
|
591 | |
)
|
|
574 |
assert humanize_error(data, e) == "expected int for dictionary value @ data['a']. Got 'not an int'\nexpected str @ data['b'][0]. Got 123"
|
592 | 575 |
else:
|
593 | 576 |
assert False, 'Did not raise MultipleInvalid'
|
594 | 577 |
|
595 | 578 |
|
596 | 579 |
def test_fix_157():
|
597 | 580 |
s = Schema(All([Any('one', 'two', 'three')]), Length(min=1))
|
598 | |
assert_equal(['one'], s(['one']))
|
599 | |
assert_raises(MultipleInvalid, s, ['four'])
|
|
581 |
assert ['one'] == s(['one'])
|
|
582 |
pytest.raises(MultipleInvalid, s, ['four'])
|
600 | 583 |
|
601 | 584 |
|
602 | 585 |
def test_range_inside():
|
603 | 586 |
s = Schema(Range(min=0, max=10))
|
604 | |
assert_equal(5, s(5))
|
|
587 |
assert 5 == s(5)
|
605 | 588 |
|
606 | 589 |
|
607 | 590 |
def test_range_outside():
|
608 | 591 |
s = Schema(Range(min=0, max=10))
|
609 | |
assert_raises(MultipleInvalid, s, 12)
|
610 | |
assert_raises(MultipleInvalid, s, -1)
|
|
592 |
with pytest.raises(MultipleInvalid):
|
|
593 |
s(12)
|
|
594 |
with pytest.raises(MultipleInvalid):
|
|
595 |
s(-1)
|
611 | 596 |
|
612 | 597 |
|
613 | 598 |
def test_range_no_upper_limit():
|
614 | 599 |
s = Schema(Range(min=0))
|
615 | |
assert_equal(123, s(123))
|
616 | |
assert_raises(MultipleInvalid, s, -1)
|
|
600 |
assert 123 == s(123)
|
|
601 |
with pytest.raises(MultipleInvalid):
|
|
602 |
s(-1)
|
617 | 603 |
|
618 | 604 |
|
619 | 605 |
def test_range_no_lower_limit():
|
620 | 606 |
s = Schema(Range(max=10))
|
621 | |
assert_equal(-1, s(-1))
|
622 | |
assert_raises(MultipleInvalid, s, 123)
|
|
607 |
assert -1 == s(-1)
|
|
608 |
with pytest.raises(MultipleInvalid):
|
|
609 |
s(123)
|
623 | 610 |
|
624 | 611 |
|
625 | 612 |
def test_range_excludes_nan():
|
626 | 613 |
s = Schema(Range(min=0, max=10))
|
627 | |
assert_raises(MultipleInvalid, s, float('nan'))
|
|
614 |
pytest.raises(MultipleInvalid, s, float('nan'))
|
628 | 615 |
|
629 | 616 |
|
630 | 617 |
def test_range_excludes_none():
|
631 | 618 |
s = Schema(Range(min=0, max=10))
|
632 | |
assert_raises(MultipleInvalid, s, None)
|
|
619 |
pytest.raises(MultipleInvalid, s, None)
|
633 | 620 |
|
634 | 621 |
|
635 | 622 |
def test_range_excludes_string():
|
636 | 623 |
s = Schema(Range(min=0, max=10))
|
637 | |
assert_raises(MultipleInvalid, s, "abc")
|
|
624 |
with pytest.raises(MultipleInvalid):
|
|
625 |
s("abc")
|
638 | 626 |
|
639 | 627 |
|
640 | 628 |
def test_range_excludes_unordered_object():
|
|
642 | 630 |
pass
|
643 | 631 |
|
644 | 632 |
s = Schema(Range(min=0, max=10))
|
645 | |
assert_raises(MultipleInvalid, s, MyObject())
|
|
633 |
pytest.raises(MultipleInvalid, s, MyObject())
|
646 | 634 |
|
647 | 635 |
|
648 | 636 |
def test_clamp_inside():
|
649 | 637 |
s = Schema(Clamp(min=1, max=10))
|
650 | |
assert_equal(5, s(5))
|
|
638 |
assert 5 == s(5)
|
651 | 639 |
|
652 | 640 |
|
653 | 641 |
def test_clamp_above():
|
654 | 642 |
s = Schema(Clamp(min=1, max=10))
|
655 | |
assert_equal(10, s(12))
|
|
643 |
assert 10 == s(12)
|
656 | 644 |
|
657 | 645 |
|
658 | 646 |
def test_clamp_below():
|
659 | 647 |
s = Schema(Clamp(min=1, max=10))
|
660 | |
assert_equal(1, s(-3))
|
|
648 |
assert 1 == s(-3)
|
661 | 649 |
|
662 | 650 |
|
663 | 651 |
def test_clamp_invalid():
|
664 | 652 |
s = Schema(Clamp(min=1, max=10))
|
665 | 653 |
if sys.version_info.major >= 3:
|
666 | |
assert_raises(MultipleInvalid, s, None)
|
667 | |
assert_raises(MultipleInvalid, s, "abc")
|
668 | |
else:
|
669 | |
assert_equal(1, s(None))
|
|
654 |
with pytest.raises(MultipleInvalid):
|
|
655 |
s(None)
|
|
656 |
with pytest.raises(MultipleInvalid):
|
|
657 |
s("abc")
|
|
658 |
else:
|
|
659 |
assert 1 == s(None)
|
670 | 660 |
|
671 | 661 |
|
672 | 662 |
def test_length_ok():
|
673 | 663 |
v1 = ['a', 'b', 'c']
|
674 | 664 |
s = Schema(Length(min=1, max=10))
|
675 | |
assert_equal(v1, s(v1))
|
|
665 |
assert v1 == s(v1)
|
676 | 666 |
v2 = "abcde"
|
677 | |
assert_equal(v2, s(v2))
|
|
667 |
assert v2 == s(v2)
|
678 | 668 |
|
679 | 669 |
|
680 | 670 |
def test_length_too_short():
|
681 | 671 |
v1 = []
|
682 | 672 |
s = Schema(Length(min=1, max=10))
|
683 | |
assert_raises(MultipleInvalid, s, v1)
|
684 | |
v2 = ''
|
685 | |
assert_raises(MultipleInvalid, s, v2)
|
|
673 |
with pytest.raises(MultipleInvalid):
|
|
674 |
s(v1)
|
|
675 |
with pytest.raises(MultipleInvalid):
|
|
676 |
v2 = ''
|
|
677 |
s(v2)
|
686 | 678 |
|
687 | 679 |
|
688 | 680 |
def test_length_too_long():
|
689 | 681 |
v = ['a', 'b', 'c']
|
690 | 682 |
s = Schema(Length(min=0, max=2))
|
691 | |
assert_raises(MultipleInvalid, s, v)
|
|
683 |
with pytest.raises(MultipleInvalid):
|
|
684 |
s(v)
|
692 | 685 |
|
693 | 686 |
|
694 | 687 |
def test_length_invalid():
|
695 | 688 |
v = None
|
696 | 689 |
s = Schema(Length(min=0, max=2))
|
697 | |
assert_raises(MultipleInvalid, s, v)
|
|
690 |
with pytest.raises(MultipleInvalid):
|
|
691 |
s(v)
|
698 | 692 |
|
699 | 693 |
|
700 | 694 |
def test_equal():
|
701 | 695 |
s = Schema(Equal(1))
|
702 | 696 |
s(1)
|
703 | |
assert_raises(Invalid, s, 2)
|
|
697 |
pytest.raises(Invalid, s, 2)
|
704 | 698 |
s = Schema(Equal('foo'))
|
705 | 699 |
s('foo')
|
706 | |
assert_raises(Invalid, s, 'bar')
|
|
700 |
pytest.raises(Invalid, s, 'bar')
|
707 | 701 |
s = Schema(Equal([1, 2]))
|
708 | 702 |
s([1, 2])
|
709 | |
assert_raises(Invalid, s, [])
|
710 | |
assert_raises(Invalid, s, [1, 2, 3])
|
|
703 |
pytest.raises(Invalid, s, [])
|
|
704 |
pytest.raises(Invalid, s, [1, 2, 3])
|
711 | 705 |
# Evaluates exactly, not through validators
|
712 | 706 |
s = Schema(Equal(str))
|
713 | |
assert_raises(Invalid, s, 'foo')
|
|
707 |
pytest.raises(Invalid, s, 'foo')
|
714 | 708 |
|
715 | 709 |
|
716 | 710 |
def test_unordered():
|
|
719 | 713 |
s([2, 1])
|
720 | 714 |
s([1, 2])
|
721 | 715 |
# Amount of errors is OK
|
722 | |
assert_raises(Invalid, s, [2, 0])
|
723 | |
assert_raises(MultipleInvalid, s, [0, 0])
|
|
716 |
pytest.raises(Invalid, s, [2, 0])
|
|
717 |
pytest.raises(MultipleInvalid, s, [0, 0])
|
724 | 718 |
# Different length is NOK
|
725 | |
assert_raises(Invalid, s, [1])
|
726 | |
assert_raises(Invalid, s, [1, 2, 0])
|
727 | |
assert_raises(MultipleInvalid, s, [1, 2, 0, 0])
|
|
719 |
pytest.raises(Invalid, s, [1])
|
|
720 |
pytest.raises(Invalid, s, [1, 2, 0])
|
|
721 |
pytest.raises(MultipleInvalid, s, [1, 2, 0, 0])
|
728 | 722 |
# Other type than list or tuple is NOK
|
729 | |
assert_raises(Invalid, s, 'foo')
|
730 | |
assert_raises(Invalid, s, 10)
|
|
723 |
pytest.raises(Invalid, s, 'foo')
|
|
724 |
pytest.raises(Invalid, s, 10)
|
731 | 725 |
# Validators are evaluated through as schemas
|
732 | 726 |
s = Schema(Unordered([int, str]))
|
733 | 727 |
s([1, '2'])
|
|
736 | 730 |
s([{'foo': 3}, []])
|
737 | 731 |
# Most accurate validators must be positioned on left
|
738 | 732 |
s = Schema(Unordered([int, 3]))
|
739 | |
assert_raises(Invalid, s, [3, 2])
|
|
733 |
pytest.raises(Invalid, s, [3, 2])
|
740 | 734 |
s = Schema(Unordered([3, int]))
|
741 | 735 |
s([3, 2])
|
742 | 736 |
|
|
745 | 739 |
s = Schema(Maybe(int))
|
746 | 740 |
assert s(1) == 1
|
747 | 741 |
assert s(None) is None
|
748 | |
assert_raises(Invalid, s, 'foo')
|
|
742 |
pytest.raises(Invalid, s, 'foo')
|
749 | 743 |
|
750 | 744 |
s = Schema(Maybe({str: Coerce(int)}))
|
751 | 745 |
assert s({'foo': '100'}) == {'foo': 100}
|
752 | 746 |
assert s(None) is None
|
753 | |
assert_raises(Invalid, s, {'foo': 'bar'})
|
|
747 |
pytest.raises(Invalid, s, {'foo': 'bar'})
|
754 | 748 |
|
755 | 749 |
|
756 | 750 |
def test_maybe_accepts_msg():
|
|
771 | 765 |
# Should trigger a MultipleInvalid exception
|
772 | 766 |
schema(3)
|
773 | 767 |
except MultipleInvalid as e:
|
774 | |
assert_equal(str(e), "not a valid value")
|
|
768 |
assert str(e) == "not a valid value"
|
775 | 769 |
else:
|
776 | 770 |
assert False, "Did not raise correct Invalid"
|
777 | 771 |
|
|
783 | 777 |
try:
|
784 | 778 |
s([123])
|
785 | 779 |
except MultipleInvalid as e:
|
786 | |
assert_equal(str(e), "not a valid value @ data[123]")
|
|
780 |
assert str(e) == "not a valid value @ data[123]"
|
787 | 781 |
else:
|
788 | 782 |
assert False, "Did not raise correct Invalid"
|
789 | 783 |
|
790 | 784 |
try:
|
791 | 785 |
s({'var': 123})
|
792 | 786 |
except MultipleInvalid as e:
|
793 | |
assert_equal(str(e), "expected a list")
|
794 | |
else:
|
795 | |
assert False, "Did not raise correct Invalid"
|
|
787 |
assert str(e) == "expected a list"
|
|
788 |
else:
|
|
789 |
assert False, "Did not raise correct Invalid"
|
796 | 790 |
|
797 | 791 |
|
798 | 792 |
def test_schema_empty_dict():
|
|
802 | 796 |
try:
|
803 | 797 |
s({'var': 123})
|
804 | 798 |
except MultipleInvalid as e:
|
805 | |
assert_equal(str(e), "extra keys not allowed @ data['var']")
|
|
799 |
assert str(e) == "extra keys not allowed @ data['var']"
|
806 | 800 |
else:
|
807 | 801 |
assert False, "Did not raise correct Invalid"
|
808 | 802 |
|
809 | 803 |
try:
|
810 | 804 |
s([123])
|
811 | 805 |
except MultipleInvalid as e:
|
812 | |
assert_equal(str(e), "expected a dictionary")
|
|
806 |
assert str(e) == "expected a dictionary"
|
813 | 807 |
else:
|
814 | 808 |
assert False, "Did not raise correct Invalid"
|
815 | 809 |
|
|
822 | 816 |
try:
|
823 | 817 |
s({'var': [123]})
|
824 | 818 |
except MultipleInvalid as e:
|
825 | |
assert_equal(str(e), "not a valid value for dictionary value @ data['var']")
|
|
819 |
assert str(e) == "not a valid value for dictionary value @ data['var']"
|
826 | 820 |
else:
|
827 | 821 |
assert False, "Did not raise correct Invalid"
|
828 | 822 |
|
|
840 | 834 |
def fn(arg):
|
841 | 835 |
return arg
|
842 | 836 |
|
843 | |
assert_raises(Invalid, fn, 1.0)
|
|
837 |
pytest.raises(Invalid, fn, 1.0)
|
844 | 838 |
|
845 | 839 |
|
846 | 840 |
def test_schema_decorator_match_with_kwargs():
|
|
856 | 850 |
def fn(arg):
|
857 | 851 |
return arg
|
858 | 852 |
|
859 | |
assert_raises(Invalid, fn, 1.0)
|
|
853 |
pytest.raises(Invalid, fn, 1.0)
|
860 | 854 |
|
861 | 855 |
|
862 | 856 |
def test_schema_decorator_match_return_with_args():
|
|
872 | 866 |
def fn(arg):
|
873 | 867 |
return "hello"
|
874 | 868 |
|
875 | |
assert_raises(Invalid, fn, 1)
|
|
869 |
pytest.raises(Invalid, fn, 1)
|
876 | 870 |
|
877 | 871 |
|
878 | 872 |
def test_schema_decorator_match_return_with_kwargs():
|
|
888 | 882 |
def fn(arg):
|
889 | 883 |
return "hello"
|
890 | 884 |
|
891 | |
assert_raises(Invalid, fn, 1)
|
|
885 |
pytest.raises(Invalid, fn, 1)
|
892 | 886 |
|
893 | 887 |
|
894 | 888 |
def test_schema_decorator_return_only_match():
|
|
904 | 898 |
def fn(arg):
|
905 | 899 |
return "hello"
|
906 | 900 |
|
907 | |
assert_raises(Invalid, fn, 1)
|
|
901 |
pytest.raises(Invalid, fn, 1)
|
908 | 902 |
|
909 | 903 |
|
910 | 904 |
def test_schema_decorator_partial_match_called_with_args():
|
|
920 | 914 |
def fn(arg1, arg2):
|
921 | 915 |
return arg1
|
922 | 916 |
|
923 | |
assert_raises(Invalid, fn, "bar", "foo")
|
|
917 |
pytest.raises(Invalid, fn, "bar", "foo")
|
924 | 918 |
|
925 | 919 |
|
926 | 920 |
def test_schema_decorator_partial_match_called_with_kwargs():
|
|
936 | 930 |
def fn(arg1, arg2):
|
937 | 931 |
return arg1
|
938 | 932 |
|
939 | |
assert_raises(Invalid, fn, arg1=1, arg2="foo")
|
|
933 |
pytest.raises(Invalid, fn, arg1=1, arg2="foo")
|
940 | 934 |
|
941 | 935 |
|
942 | 936 |
def test_unicode_as_key():
|
943 | 937 |
if sys.version_info >= (3,):
|
944 | 938 |
text_type = str
|
945 | 939 |
else:
|
946 | |
text_type = unicode
|
|
940 |
text_type = unicode # noqa: F821
|
947 | 941 |
schema = Schema({text_type: int})
|
948 | 942 |
schema({u("foobar"): 1})
|
949 | 943 |
|
|
954 | 948 |
try:
|
955 | 949 |
schema({"number": 'teststr'})
|
956 | 950 |
except MultipleInvalid as e:
|
957 | |
assert_equal(str(e),
|
958 | |
"Value must be a number enclosed with string for dictionary value @ data['number']")
|
|
951 |
assert str(e) == "Value must be a number enclosed with string for dictionary value @ data['number']"
|
959 | 952 |
else:
|
960 | 953 |
assert False, "Did not raise Invalid for String"
|
961 | 954 |
|
|
966 | 959 |
try:
|
967 | 960 |
schema({"number": '123456.712'})
|
968 | 961 |
except MultipleInvalid as e:
|
969 | |
assert_equal(str(e),
|
970 | |
"Precision must be equal to 6, and Scale must be equal to 2 for dictionary value @ data['number']")
|
|
962 |
assert str(e) == "Precision must be equal to 6, and Scale must be equal to 2 for dictionary value @ data['number']"
|
971 | 963 |
else:
|
972 | 964 |
assert False, "Did not raise Invalid for String"
|
973 | 965 |
|
|
976 | 968 |
""" Test with Number with valid precision and scale"""
|
977 | 969 |
schema = Schema({"number": Number(precision=6, scale=2, yield_decimal=True)})
|
978 | 970 |
out_ = schema({"number": '1234.00'})
|
979 | |
assert_equal(float(out_.get("number")), 1234.00)
|
|
971 |
assert float(out_.get("number")) == 1234.00
|
980 | 972 |
|
981 | 973 |
|
982 | 974 |
def test_number_when_precision_scale_none_yield_decimal_true():
|
983 | 975 |
""" Test with Number with no precision and scale"""
|
984 | 976 |
schema = Schema({"number": Number(yield_decimal=True)})
|
985 | 977 |
out_ = schema({"number": '12345678901234'})
|
986 | |
assert_equal(out_.get("number"), 12345678901234)
|
|
978 |
assert out_.get("number") == 12345678901234
|
987 | 979 |
|
988 | 980 |
|
989 | 981 |
def test_number_when_precision_none_n_valid_scale_case1_yield_decimal_true():
|
990 | 982 |
""" Test with Number with no precision and valid scale case 1"""
|
991 | 983 |
schema = Schema({"number": Number(scale=2, yield_decimal=True)})
|
992 | 984 |
out_ = schema({"number": '123456789.34'})
|
993 | |
assert_equal(float(out_.get("number")), 123456789.34)
|
|
985 |
assert float(out_.get("number")) == 123456789.34
|
994 | 986 |
|
995 | 987 |
|
996 | 988 |
def test_number_when_precision_none_n_valid_scale_case2_yield_decimal_true():
|
997 | 989 |
""" Test with Number with no precision and valid scale case 2 with zero in decimal part"""
|
998 | 990 |
schema = Schema({"number": Number(scale=2, yield_decimal=True)})
|
999 | 991 |
out_ = schema({"number": '123456789012.00'})
|
1000 | |
assert_equal(float(out_.get("number")), 123456789012.00)
|
|
992 |
assert float(out_.get("number")) == 123456789012.00
|
1001 | 993 |
|
1002 | 994 |
|
1003 | 995 |
def test_number_when_precision_none_n_invalid_scale_yield_decimal_true():
|
|
1006 | 998 |
try:
|
1007 | 999 |
schema({"number": '12345678901.234'})
|
1008 | 1000 |
except MultipleInvalid as e:
|
1009 | |
assert_equal(str(e),
|
1010 | |
"Scale must be equal to 2 for dictionary value @ data['number']")
|
|
1001 |
assert str(e) == "Scale must be equal to 2 for dictionary value @ data['number']"
|
1011 | 1002 |
else:
|
1012 | 1003 |
assert False, "Did not raise Invalid for String"
|
1013 | 1004 |
|
|
1016 | 1007 |
""" Test with Number with no precision and valid scale"""
|
1017 | 1008 |
schema = Schema({"number": Number(precision=14, yield_decimal=True)})
|
1018 | 1009 |
out_ = schema({"number": '1234567.8901234'})
|
1019 | |
assert_equal(float(out_.get("number")), 1234567.8901234)
|
|
1010 |
assert float(out_.get("number")) == 1234567.8901234
|
1020 | 1011 |
|
1021 | 1012 |
|
1022 | 1013 |
def test_number_when_invalid_precision_n_scale_none_yield_decimal_true():
|
|
1025 | 1016 |
try:
|
1026 | 1017 |
schema({"number": '12345674.8901234'})
|
1027 | 1018 |
except MultipleInvalid as e:
|
1028 | |
assert_equal(str(e),
|
1029 | |
"Precision must be equal to 14 for dictionary value @ data['number']")
|
|
1019 |
assert str(e) == "Precision must be equal to 14 for dictionary value @ data['number']"
|
1030 | 1020 |
else:
|
1031 | 1021 |
assert False, "Did not raise Invalid for String"
|
1032 | 1022 |
|
|
1035 | 1025 |
""" Test with Number with valid precision, scale and no yield_decimal"""
|
1036 | 1026 |
schema = Schema({"number": Number(precision=6, scale=2, yield_decimal=False)})
|
1037 | 1027 |
out_ = schema({"number": '1234.00'})
|
1038 | |
assert_equal(out_.get("number"), '1234.00')
|
|
1028 |
assert out_.get("number") == '1234.00'
|
1039 | 1029 |
|
1040 | 1030 |
|
1041 | 1031 |
def test_named_tuples_validate_as_tuples():
|
|
1052 | 1042 |
def test_datetime():
|
1053 | 1043 |
schema = Schema({"datetime": Datetime()})
|
1054 | 1044 |
schema({"datetime": "2016-10-24T14:01:57.102152Z"})
|
1055 | |
assert_raises(MultipleInvalid, schema, {"datetime": "2016-10-24T14:01:57"})
|
|
1045 |
pytest.raises(MultipleInvalid, schema, {"datetime": "2016-10-24T14:01:57"})
|
1056 | 1046 |
|
1057 | 1047 |
|
1058 | 1048 |
def test_date():
|
1059 | 1049 |
schema = Schema({"date": Date()})
|
1060 | 1050 |
schema({"date": "2016-10-24"})
|
1061 | |
assert_raises(MultipleInvalid, schema, {"date": "2016-10-24Z"})
|
|
1051 |
pytest.raises(MultipleInvalid, schema, {"date": "2016-10-24Z"})
|
1062 | 1052 |
|
1063 | 1053 |
|
1064 | 1054 |
def test_date_custom_format():
|
1065 | 1055 |
schema = Schema({"date": Date("%Y%m%d")})
|
1066 | 1056 |
schema({"date": "20161024"})
|
1067 | |
assert_raises(MultipleInvalid, schema, {"date": "2016-10-24"})
|
|
1057 |
pytest.raises(MultipleInvalid, schema, {"date": "2016-10-24"})
|
1068 | 1058 |
|
1069 | 1059 |
|
1070 | 1060 |
def test_ordered_dict():
|
|
1086 | 1076 |
Required('x'): int, Optional('y'): float,
|
1087 | 1077 |
Remove('j'): int, Remove(int): str, int: int
|
1088 | 1078 |
}
|
1089 | |
assert_equal(definition.get('x'), int)
|
1090 | |
assert_equal(definition.get('y'), float)
|
1091 | |
assert_true(Required('x') == Required('x'))
|
1092 | |
assert_true(Required('x') != Required('y'))
|
|
1079 |
assert definition.get('x') == int
|
|
1080 |
assert definition.get('y') == float
|
|
1081 |
assert Required('x') == Required('x')
|
|
1082 |
assert Required('x') != Required('y')
|
1093 | 1083 |
# Remove markers are not hashable
|
1094 | |
assert_equal(definition.get('j'), None)
|
|
1084 |
assert definition.get('j') is None
|
1095 | 1085 |
|
1096 | 1086 |
|
1097 | 1087 |
def test_schema_infer():
|
|
1101 | 1091 |
'int': 42,
|
1102 | 1092 |
'float': 3.14
|
1103 | 1093 |
})
|
1104 | |
assert_equal(schema, Schema({
|
|
1094 |
assert schema == Schema({
|
1105 | 1095 |
Required('str'): str,
|
1106 | 1096 |
Required('bool'): bool,
|
1107 | 1097 |
Required('int'): int,
|
1108 | 1098 |
Required('float'): float
|
1109 | |
}))
|
|
1099 |
})
|
1110 | 1100 |
|
1111 | 1101 |
|
1112 | 1102 |
def test_schema_infer_dict():
|
|
1118 | 1108 |
}
|
1119 | 1109 |
})
|
1120 | 1110 |
|
1121 | |
assert_equal(schema, Schema({
|
|
1111 |
assert schema == Schema({
|
1122 | 1112 |
Required('a'): {
|
1123 | 1113 |
Required('b'): {
|
1124 | 1114 |
Required('c'): str
|
1125 | 1115 |
}
|
1126 | 1116 |
}
|
1127 | |
}))
|
|
1117 |
})
|
1128 | 1118 |
|
1129 | 1119 |
|
1130 | 1120 |
def test_schema_infer_list():
|
|
1132 | 1122 |
'list': ['foo', True, 42, 3.14]
|
1133 | 1123 |
})
|
1134 | 1124 |
|
1135 | |
assert_equal(schema, Schema({
|
|
1125 |
assert schema == Schema({
|
1136 | 1126 |
Required('list'): [str, bool, int, float]
|
1137 | |
}))
|
|
1127 |
})
|
1138 | 1128 |
|
1139 | 1129 |
|
1140 | 1130 |
def test_schema_infer_scalar():
|
1141 | |
assert_equal(Schema.infer('foo'), Schema(str))
|
1142 | |
assert_equal(Schema.infer(True), Schema(bool))
|
1143 | |
assert_equal(Schema.infer(42), Schema(int))
|
1144 | |
assert_equal(Schema.infer(3.14), Schema(float))
|
1145 | |
assert_equal(Schema.infer({}), Schema(dict))
|
1146 | |
assert_equal(Schema.infer([]), Schema(list))
|
|
1131 |
assert Schema.infer('foo') == Schema(str)
|
|
1132 |
assert Schema.infer(True) == Schema(bool)
|
|
1133 |
assert Schema.infer(42) == Schema(int)
|
|
1134 |
assert Schema.infer(3.14) == Schema(float)
|
|
1135 |
assert Schema.infer({}) == Schema(dict)
|
|
1136 |
assert Schema.infer([]) == Schema(list)
|
1147 | 1137 |
|
1148 | 1138 |
|
1149 | 1139 |
def test_schema_infer_accepts_kwargs():
|
|
1206 | 1196 |
|
1207 | 1197 |
def test_IsDir():
|
1208 | 1198 |
schema = Schema(IsDir())
|
1209 | |
assert_raises(MultipleInvalid, schema, 3)
|
|
1199 |
pytest.raises(MultipleInvalid, schema, 3)
|
1210 | 1200 |
schema(os.path.dirname(os.path.abspath(__file__)))
|
1211 | 1201 |
|
1212 | 1202 |
|
1213 | 1203 |
def test_IsFile():
|
1214 | 1204 |
schema = Schema(IsFile())
|
1215 | |
assert_raises(MultipleInvalid, schema, 3)
|
|
1205 |
pytest.raises(MultipleInvalid, schema, 3)
|
1216 | 1206 |
schema(os.path.abspath(__file__))
|
1217 | 1207 |
|
1218 | 1208 |
|
1219 | 1209 |
def test_PathExists():
|
1220 | 1210 |
schema = Schema(PathExists())
|
1221 | |
assert_raises(MultipleInvalid, schema, 3)
|
|
1211 |
pytest.raises(MultipleInvalid, schema, 3)
|
1222 | 1212 |
schema(os.path.abspath(__file__))
|
1223 | 1213 |
|
1224 | 1214 |
|
|
1300 | 1290 |
s({'q': 'str', 'q2': 'tata'})
|
1301 | 1291 |
except MultipleInvalid as exc:
|
1302 | 1292 |
assert (
|
1303 | |
(exc.errors[0].path == ['q'] and exc.errors[1].path == ['q2']) or
|
1304 | |
(exc.errors[1].path == ['q'] and exc.errors[0].path == ['q2'])
|
|
1293 |
(exc.errors[0].path == ['q'] and exc.errors[1].path == ['q2'])
|
|
1294 |
or (exc.errors[1].path == ['q'] and exc.errors[0].path == ['q2'])
|
1305 | 1295 |
)
|
1306 | 1296 |
else:
|
1307 | 1297 |
assert False, "Did not raise AnyInvalid"
|
|
1317 | 1307 |
s({'q': 'str', 'q2': 12})
|
1318 | 1308 |
except MultipleInvalid as exc:
|
1319 | 1309 |
assert (
|
1320 | |
(exc.errors[0].path == ['q'] and exc.errors[1].path == ['q2']) or
|
1321 | |
(exc.errors[1].path == ['q'] and exc.errors[0].path == ['q2'])
|
|
1310 |
(exc.errors[0].path == ['q'] and exc.errors[1].path == ['q2'])
|
|
1311 |
or (exc.errors[1].path == ['q'] and exc.errors[0].path == ['q2'])
|
1322 | 1312 |
)
|
1323 | 1313 |
else:
|
1324 | 1314 |
assert False, "Did not raise AllInvalid"
|
|
1392 | 1382 |
|
1393 | 1383 |
|
1394 | 1384 |
def test_comparing_voluptuous_object_to_str():
|
1395 | |
assert_true(Optional('Classification') < 'Name')
|
|
1385 |
assert Optional('Classification') < 'Name'
|
1396 | 1386 |
|
1397 | 1387 |
|
1398 | 1388 |
def test_set_of_integers():
|
|
1408 | 1398 |
try:
|
1409 | 1399 |
schema(set(['abc']))
|
1410 | 1400 |
except MultipleInvalid as e:
|
1411 | |
assert_equal(str(e), "invalid value in set")
|
|
1401 |
assert str(e) == "invalid value in set"
|
1412 | 1402 |
else:
|
1413 | 1403 |
assert False, "Did not raise Invalid"
|
1414 | 1404 |
|
|
1426 | 1416 |
try:
|
1427 | 1417 |
schema(frozenset(['abc']))
|
1428 | 1418 |
except MultipleInvalid as e:
|
1429 | |
assert_equal(str(e), "invalid value in frozenset")
|
|
1419 |
assert str(e) == "invalid value in frozenset"
|
1430 | 1420 |
else:
|
1431 | 1421 |
assert False, "Did not raise Invalid"
|
1432 | 1422 |
|
|
1443 | 1433 |
try:
|
1444 | 1434 |
schema(set([None]))
|
1445 | 1435 |
except MultipleInvalid as e:
|
1446 | |
assert_equal(str(e), "invalid value in set")
|
|
1436 |
assert str(e) == "invalid value in set"
|
1447 | 1437 |
else:
|
1448 | 1438 |
assert False, "Did not raise Invalid"
|
1449 | 1439 |
|
|
1460 | 1450 |
try:
|
1461 | 1451 |
schema(frozenset([None]))
|
1462 | 1452 |
except MultipleInvalid as e:
|
1463 | |
assert_equal(str(e), "invalid value in frozenset")
|
|
1453 |
assert str(e) == "invalid value in frozenset"
|
1464 | 1454 |
else:
|
1465 | 1455 |
assert False, "Did not raise Invalid"
|
1466 | 1456 |
|
|
1506 | 1496 |
try:
|
1507 | 1497 |
schema({})
|
1508 | 1498 |
except MultipleInvalid as e:
|
1509 | |
assert_equal(str(e),
|
1510 | |
"required key not provided @ data['a']")
|
|
1499 |
assert str(e) == "required key not provided @ data['a']"
|
1511 | 1500 |
else:
|
1512 | 1501 |
assert False, "Did not raise Invalid for MultipleInvalid"
|
1513 | 1502 |
|
|
1521 | 1510 |
try:
|
1522 | 1511 |
schema({})
|
1523 | 1512 |
except MultipleInvalid as e:
|
1524 | |
assert_equal(str(e),
|
1525 | |
"required key not provided @ data['a']")
|
|
1513 |
assert str(e) == "required key not provided @ data['a']"
|
1526 | 1514 |
else:
|
1527 | 1515 |
assert False, "Did not raise Invalid for MultipleInvalid"
|
1528 | 1516 |
|
1529 | 1517 |
|
1530 | 1518 |
def test_inclusive():
|
1531 | 1519 |
schema = Schema({
|
1532 | |
Inclusive('x', 'stuff'): int,
|
1533 | |
Inclusive('y', 'stuff'): int,
|
1534 | |
})
|
|
1520 |
Inclusive('x', 'stuff'): int,
|
|
1521 |
Inclusive('y', 'stuff'): int,
|
|
1522 |
})
|
1535 | 1523 |
|
1536 | 1524 |
r = schema({})
|
1537 | |
assert_equal(r, {})
|
|
1525 |
assert r == {}
|
1538 | 1526 |
|
1539 | 1527 |
r = schema({'x': 1, 'y': 2})
|
1540 | |
assert_equal(r, {'x': 1, 'y': 2})
|
|
1528 |
assert r == {'x': 1, 'y': 2}
|
1541 | 1529 |
|
1542 | 1530 |
try:
|
1543 | 1531 |
r = schema({'x': 1})
|
1544 | 1532 |
except MultipleInvalid as e:
|
1545 | |
assert_equal(str(e),
|
1546 | |
"some but not all values in the same group of inclusion 'stuff' @ data[<stuff>]")
|
|
1533 |
assert str(e) == "some but not all values in the same group of inclusion 'stuff' @ data[<stuff>]"
|
1547 | 1534 |
else:
|
1548 | 1535 |
assert False, "Did not raise Invalid for incomplete Inclusive group"
|
1549 | 1536 |
|
1550 | 1537 |
|
1551 | 1538 |
def test_inclusive_defaults():
|
1552 | 1539 |
schema = Schema({
|
1553 | |
Inclusive('x', 'stuff', default=3): int,
|
1554 | |
Inclusive('y', 'stuff', default=4): int,
|
1555 | |
})
|
|
1540 |
Inclusive('x', 'stuff', default=3): int,
|
|
1541 |
Inclusive('y', 'stuff', default=4): int,
|
|
1542 |
})
|
1556 | 1543 |
|
1557 | 1544 |
r = schema({})
|
1558 | |
assert_equal(r, {'x': 3, 'y': 4})
|
|
1545 |
assert r == {'x': 3, 'y': 4}
|
1559 | 1546 |
|
1560 | 1547 |
try:
|
1561 | 1548 |
r = schema({'x': 1})
|
1562 | 1549 |
except MultipleInvalid as e:
|
1563 | |
assert_equal(str(e),
|
1564 | |
"some but not all values in the same group of inclusion 'stuff' @ data[<stuff>]")
|
|
1550 |
assert str(e) == "some but not all values in the same group of inclusion 'stuff' @ data[<stuff>]"
|
1565 | 1551 |
else:
|
1566 | 1552 |
assert False, "Did not raise Invalid for incomplete Inclusive group with defaults"
|
1567 | 1553 |
|
1568 | 1554 |
|
1569 | 1555 |
def test_exclusive():
|
1570 | 1556 |
schema = Schema({
|
1571 | |
Exclusive('x', 'stuff'): int,
|
1572 | |
Exclusive('y', 'stuff'): int,
|
1573 | |
})
|
|
1557 |
Exclusive('x', 'stuff'): int,
|
|
1558 |
Exclusive('y', 'stuff'): int,
|
|
1559 |
})
|
1574 | 1560 |
|
1575 | 1561 |
r = schema({})
|
1576 | |
assert_equal(r, {})
|
|
1562 |
assert r == {}
|
1577 | 1563 |
|
1578 | 1564 |
r = schema({'x': 1})
|
1579 | |
assert_equal(r, {'x': 1})
|
|
1565 |
assert r == {'x': 1}
|
1580 | 1566 |
|
1581 | 1567 |
try:
|
1582 | 1568 |
r = schema({'x': 1, 'y': 2})
|
1583 | 1569 |
except MultipleInvalid as e:
|
1584 | |
assert_equal(str(e),
|
1585 | |
"two or more values in the same group of exclusion 'stuff' @ data[<stuff>]")
|
|
1570 |
assert str(e) == "two or more values in the same group of exclusion 'stuff' @ data[<stuff>]"
|
1586 | 1571 |
else:
|
1587 | 1572 |
assert False, "Did not raise Invalid for multiple values in Exclusive group"
|
1588 | 1573 |
|
|
1608 | 1593 |
}
|
1609 | 1594 |
})
|
1610 | 1595 |
except MultipleInvalid as e:
|
1611 | |
assert_equal(str(e), 'expected bool for dictionary value @ data[\'implementation\'][\'c-value\']')
|
|
1596 |
assert str(e) == 'expected bool for dictionary value @ data[\'implementation\'][\'c-value\']'
|
1612 | 1597 |
else:
|
1613 | 1598 |
assert False, "Did not raise correct Invalid"
|
1614 | 1599 |
|
1615 | |
def test_coerce_enum():
|
1616 | |
"""Test Coerce Enum"""
|
1617 | |
class Choice(Enum):
|
1618 | |
Easy = 1
|
1619 | |
Medium = 2
|
1620 | |
Hard = 3
|
1621 | |
|
1622 | |
class StringChoice(str, Enum):
|
1623 | |
Easy = "easy"
|
1624 | |
Medium = "medium"
|
1625 | |
Hard = "hard"
|
1626 | |
|
1627 | |
schema = Schema(Coerce(Choice))
|
1628 | |
string_schema = Schema(Coerce(StringChoice))
|
1629 | |
|
1630 | |
# Valid value
|
1631 | |
assert schema(1) == Choice.Easy
|
1632 | |
assert string_schema("easy") == StringChoice.Easy
|
1633 | |
|
1634 | |
# Invalid value
|
1635 | |
try:
|
1636 | |
schema(4)
|
1637 | |
except Invalid as e:
|
1638 | |
assert_equal(str(e),
|
1639 | |
"expected Choice or one of 1, 2, 3")
|
1640 | |
else:
|
1641 | |
assert False, "Did not raise Invalid for String"
|
1642 | |
|
1643 | |
try:
|
1644 | |
string_schema("hello")
|
1645 | |
except Invalid as e:
|
1646 | |
assert_equal(str(e),
|
1647 | |
"expected StringChoice or one of 'easy', 'medium', 'hard'")
|
1648 | |
else:
|
1649 | |
assert False, "Did not raise Invalid for String"
|
|
1600 |
|
|
1601 |
if Enum:
|
|
1602 |
def test_coerce_enum():
|
|
1603 |
"""Test Coerce Enum"""
|
|
1604 |
class Choice(Enum):
|
|
1605 |
Easy = 1
|
|
1606 |
Medium = 2
|
|
1607 |
Hard = 3
|
|
1608 |
|
|
1609 |
class StringChoice(str, Enum):
|
|
1610 |
Easy = "easy"
|
|
1611 |
Medium = "medium"
|
|
1612 |
Hard = "hard"
|
|
1613 |
|
|
1614 |
schema = Schema(Coerce(Choice))
|
|
1615 |
string_schema = Schema(Coerce(StringChoice))
|
|
1616 |
|
|
1617 |
# Valid value
|
|
1618 |
assert schema(1) == Choice.Easy
|
|
1619 |
assert string_schema("easy") == StringChoice.Easy
|
|
1620 |
|
|
1621 |
# Invalid value
|
|
1622 |
try:
|
|
1623 |
schema(4)
|
|
1624 |
except Invalid as e:
|
|
1625 |
assert str(e) == "expected Choice or one of 1, 2, 3"
|
|
1626 |
else:
|
|
1627 |
assert False, "Did not raise Invalid for String"
|
|
1628 |
|
|
1629 |
try:
|
|
1630 |
string_schema("hello")
|
|
1631 |
except Invalid as e:
|
|
1632 |
assert str(e) == "expected StringChoice or one of 'easy', 'medium', 'hard'"
|
|
1633 |
else:
|
|
1634 |
assert False, "Did not raise Invalid for String"
|
|
1635 |
|
|
1636 |
|
|
1637 |
class MyValueClass(object):
|
|
1638 |
def __init__(self, value=None):
|
|
1639 |
self.value = value
|
|
1640 |
|
|
1641 |
|
|
1642 |
def test_object():
|
|
1643 |
s = Schema(Object({'value': 1}), required=True)
|
|
1644 |
s(MyValueClass(value=1))
|
|
1645 |
pytest.raises(MultipleInvalid, s, MyValueClass(value=2))
|
|
1646 |
pytest.raises(MultipleInvalid, s, 345)
|
|
1647 |
|
|
1648 |
|
|
1649 |
# Python 3.7 removed the trailing comma in repr() of BaseException
|
|
1650 |
# https://bugs.python.org/issue30399
|
|
1651 |
if sys.version_info >= (3, 7):
|
|
1652 |
invalid_scalar_excp_repr = "ScalarInvalid('not a valid value')"
|
|
1653 |
else:
|
|
1654 |
invalid_scalar_excp_repr = "ScalarInvalid('not a valid value',)"
|
|
1655 |
|
|
1656 |
|
|
1657 |
def test_exception():
|
|
1658 |
s = Schema(None)
|
|
1659 |
try:
|
|
1660 |
s(123)
|
|
1661 |
except MultipleInvalid as e:
|
|
1662 |
assert repr(e) == "MultipleInvalid([{}])".format(invalid_scalar_excp_repr)
|
|
1663 |
assert str(e.msg) == "not a valid value"
|
|
1664 |
assert str(e.error_message) == "not a valid value"
|
|
1665 |
assert str(e.errors) == "[{}]".format(invalid_scalar_excp_repr)
|
|
1666 |
e.add("Test Error")
|
|
1667 |
assert str(e.errors) == "[{}, 'Test Error']".format(invalid_scalar_excp_repr)
|