comparison tests/test_schema.py @ 5:84dfd1a94926

Add the existing implementation. All tests work. The documentation as text file is included also.
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 06 Jul 2023 23:41:41 +0200
parents
children 940676a0de84
comparison
equal deleted inserted replaced
4:d715f0c13c60 5:84dfd1a94926
1
2 import copy
3 import datetime
4 import re
5 import unittest
6
7 import _config
8
9 import configmix.yaml
10
11 import data_schema
12 import data_schema.util
13
14
15 TYPE_RE = type(re.compile(r"\A.+\Z"))
16
17
18 def _test_generic_validator_for_yaml(obj, schema, context):
19 """Callback for loading test1.schema.yml: Always successful"""
20 yield from ()
21
22
23 class YAML(unittest.TestCase):
24
25 """Tests to load Python objects from YAML with complex Python-specific
26 tags.
27
28 .. seealso:: https://pyyaml.org/wiki/PyYAMLDocumentation
29
30 """
31
32 def test_load_python_name(self):
33 y = configmix.yaml.load("key: !!python/name:data_schema.validate")
34 self.assertTrue(callable(y["key"]))
35
36 def test_load_re(self):
37 y = configmix.yaml.load("key: !!python/object/apply:re.compile\n - '^[0-9]+$'")
38 self.assertTrue(isinstance(y["key"], TYPE_RE))
39
40
41 class SchemaInYAML(unittest.TestCase):
42 def test_file(self):
43 with data_schema.util.get_data_stream(
44 _config.FILEURI_PREFIX + "test1.schema.yml",
45 basedir=_config.config.getvar_s("projectdir")) as f:
46 schema = data_schema._Schema(
47 None, True, configmix.yaml.load(f))
48
49 def test_data(self):
50 with data_schema.util.get_data_stream(
51 "data:testschematalib:test2.schema.yml") as f:
52 schema = data_schema._Schema(
53 None, True, configmix.yaml.load(f))
54
55
56 class SchemaCheck(unittest.TestCase):
57
58 def test_root_creation(self):
59 schema = data_schema._Schema(None, True)
60 self.assertIsInstance(schema, dict)
61 self.assertEqual(0, len(schema))
62 self.assertFalse(schema)
63
64 def test_root_creation_wrong(self):
65 self.assertRaises(
66 ValueError,
67 data_schema._Schema,
68 None,
69 False)
70
71 def test_root_properties(self):
72 schema = data_schema._Schema(None, True)
73 self.assertIsNone(schema.parent)
74 self.assertIs(schema, schema.ROOT)
75 self.assertTrue(schema.is_sub_root)
76 self.assertIs(schema, schema.SELF)
77
78 def test_dict_len_bool(self):
79 schema = data_schema._Schema(None, True, a=1, b=2)
80 self.assertTrue(schema)
81 self.assertEqual(2, len(schema))
82
83 def test_equality(self):
84 schema1 = data_schema._Schema(None, True, a=1, b=2)
85 schema2 = data_schema._Schema(None, True, b=2, a=1)
86 self.assertEqual(schema1, schema2)
87 self.assertIsNot(schema1, schema2)
88
89 def test_copy(self):
90 schema = data_schema._Schema(None, True, type="str")
91 schema2 = schema.copy()
92 self.assertEqual(schema, schema2)
93
94 def test_deepcopy(self):
95 d1 = {}
96 schema = data_schema._Schema(None, True, type="str", b=d1)
97 schema2 = copy.deepcopy(schema)
98 self.assertEqual(schema, schema2)
99 self.assertIs(schema["b"], d1)
100 self.assertIsNot(schema2["b"], d1)
101 self.assertIs(schema.parent, schema2.parent)
102 self.assertIs(schema.is_sub_root, schema2.is_sub_root)
103
104 def test_nested_copy(self):
105 d1 = {}
106 d2 = {}
107 root_schema = data_schema._Schema(None, True, type="str", b=d1)
108 child_schema = data_schema._Schema(root_schema, True, type="bool", b=d2)
109 copied_child = child_schema.copy()
110 self.assertIs(copied_child.ROOT, root_schema)
111 self.assertIs(copied_child.SELF, copied_child)
112 self.assertIsNot(copied_child.SELF, root_schema)
113 self.assertEqual(child_schema, copied_child)
114 self.assertIs(copied_child["b"], d2)
115
116 def test_nested_deepcopy(self):
117 d1 = {}
118 d2 = {}
119 root_schema = data_schema._Schema(None, True, type="str", b=d1)
120 child_schema = data_schema._Schema(root_schema, True, type="bool", b=d2)
121 copied_child = copy.deepcopy(child_schema)
122 self.assertIs(copied_child.ROOT, root_schema)
123 self.assertIs(copied_child.SELF, copied_child)
124 self.assertEqual(child_schema, copied_child)
125 self.assertIsNot(copied_child["b"], d2)
126 self.assertNotEqual(root_schema, child_schema)
127
128
129 class ContextCheck(unittest.TestCase):
130
131 def test_root_without_settings(self):
132 self.assertRaises(TypeError,
133 data_schema.Context,
134 None,
135 root_object=object(),
136 schema=dict())
137
138 def test_root_context(self):
139 obj = object()
140 schema = object()
141 settings = data_schema.ValidationSettings(
142 skip_keys=[], break_on_keynames_problems=True)
143 ctx = data_schema.Context(
144 None, root_object=obj, root_schema=schema, settings=settings)
145 self.assertEqual("<ROOT>", str(ctx))
146 self.assertTrue(ctx.root_object is obj)
147 self.assertTrue(ctx.root_schema is schema)
148 self.assertTrue(ctx.settings is settings)
149
150 def test_parent_of_root_context(self):
151 obj = object()
152 schema = object()
153 settings = data_schema.ValidationSettings(
154 skip_keys=[], break_on_keynames_problems=True)
155 ctx = data_schema.Context(
156 None, root_object=obj, root_schema=schema, settings=settings)
157 self.assertTrue(ctx.is_root)
158 self.assertIsNone(ctx.parent)
159 try:
160 ctx.safe_parent
161 except TypeError:
162 pass
163 else:
164 self.fail(
165 "Context.safe_parent was expected to raise for a root context")
166
167 def test_root_context_init_root_empty(self):
168 settings = data_schema.ValidationSettings(
169 skip_keys=[], break_on_keynames_problems=True)
170 self.assertRaises(
171 TypeError,
172 data_schema.Context, None, key="key", settings=settings)
173 self.assertRaises(
174 TypeError,
175 data_schema.Context, None, index="key", settings=settings)
176
177 def test_root_context_init_only_one_of_key_index(self):
178 settings = data_schema.ValidationSettings(
179 skip_keys=[], break_on_keynames_problems=True)
180 root = data_schema.Context(None, settings=settings)
181 self.assertRaises(
182 ValueError,
183 data_schema.Context, root, key="key", index="index")
184
185 def test_root_context_init_exactly_one(self):
186 settings = data_schema.ValidationSettings(
187 skip_keys=[], break_on_keynames_problems=True)
188 root = data_schema.Context(None, settings=settings)
189 self.assertRaises(TypeError, data_schema.Context, root)
190
191 def test_nonroot_rootobj_schema(self):
192 settings = data_schema.ValidationSettings(
193 skip_keys=[], break_on_keynames_problems=True)
194 obj = object()
195 schema = object()
196 ctx = data_schema.Context(
197 None, root_object=obj, root_schema=schema, settings=settings)
198 self.assertEqual("<ROOT>", str(ctx))
199 self.assertTrue(ctx.root_object is obj)
200 self.assertTrue(ctx.root_schema is schema)
201 self.assertTrue(ctx.settings is settings)
202 self.assertRaises(TypeError, data_schema.Context, ctx, index=0,
203 root_object=object())
204 self.assertRaises(TypeError, data_schema.Context, ctx, index=0,
205 root_schema=object())
206
207 def test_str(self):
208 settings = data_schema.ValidationSettings(
209 skip_keys=[], break_on_keynames_problems=True)
210 root = data_schema.Context(None, settings=settings)
211 ctx1 = data_schema.Context(root, key="key1")
212 ctx2 = data_schema.Context(ctx1, index=2)
213 ctx3 = data_schema.Context(ctx2, key="key3")
214 self.assertEqual("key1 / INDEX:2 / key3", str(ctx3))
215
216 def test_repr(self):
217 settings = data_schema.ValidationSettings(
218 skip_keys=[], break_on_keynames_problems=True)
219 root = data_schema.Context(None, settings=settings)
220 ctx1 = data_schema.Context(root, key="key1")
221 ctx2 = data_schema.Context(ctx1, index=2)
222 ctx3 = data_schema.Context(ctx2, key="key3")
223 self.assertEqual("<Context path=`key1 / INDEX:2 / key3'>", repr(ctx3))
224
225 def test_root(self):
226 settings = data_schema.ValidationSettings(
227 skip_keys=[], break_on_keynames_problems=True)
228 root = data_schema.Context(None, settings=settings)
229 self.assertTrue(root.is_root)
230 self.assertTrue(root is root.root)
231 self.assertTrue(root.settings is settings)
232 ctx1 = data_schema.Context(root, key="key1")
233 self.assertFalse(ctx1.is_root)
234 self.assertTrue(ctx1.root is root)
235 self.assertTrue(ctx1.settings is settings)
236 ctx2 = data_schema.Context(ctx1, index=2)
237 self.assertTrue(ctx2.settings is settings)
238 ctx3 = data_schema.Context(ctx2, key="key3")
239 self.assertEqual("key1 / INDEX:2 / key3", str(ctx3))
240 self.assertFalse(ctx3.is_root)
241 self.assertTrue(ctx3.root is root)
242 self.assertTrue(ctx3.settings is settings)
243
244 def test_extra_settings_in_between(self):
245 settings = data_schema.ValidationSettings(
246 skip_keys=[], break_on_keynames_problems=True)
247 settings2 = data_schema.ValidationSettings(
248 skip_keys=[], break_on_keynames_problems=True)
249 root = data_schema.Context(None, settings=settings)
250 self.assertTrue(root.is_root)
251 self.assertTrue(root is root.root)
252 self.assertTrue(root.settings is settings)
253 ctx1 = data_schema.Context(root, key="key1")
254 self.assertFalse(ctx1.is_root)
255 self.assertTrue(ctx1.root is root)
256 self.assertTrue(ctx1.settings is settings)
257 ctx2 = data_schema.Context(ctx1, index=2, settings=settings2)
258 self.assertTrue(ctx2.settings is settings2)
259 ctx3 = data_schema.Context(ctx2, key="key3")
260 self.assertEqual("key1 / INDEX:2 / key3", str(ctx3))
261 self.assertFalse(ctx3.is_root)
262 self.assertTrue(ctx3.root is root)
263 self.assertTrue(ctx3.settings is settings2)
264
265 def test_key_xor_index(self):
266 settings = data_schema.ValidationSettings(
267 skip_keys=[], break_on_keynames_problems=True)
268 root = data_schema.Context(None, settings=settings)
269 self.assertRaises(
270 ValueError,
271 data_schema.Context,
272 root,
273 index=0,
274 key="huhu")
275
276 def test_keyindex_requires_key(self):
277 settings = data_schema.ValidationSettings(
278 skip_keys=[], break_on_keynames_problems=True)
279 self.assertRaises(
280 ValueError,
281 data_schema.Context,
282 None,
283 key_index=0,
284 settings=settings)
285
286
287 class SchemaReferences(unittest.TestCase):
288
289 def setUp(self):
290 self.empty_schema = data_schema._Schema(None, True)
291
292 def test_no_fragment(self):
293 ctx = data_schema.Context(None, root_object={"foo": "bar"}, settings=None)
294 self.assertRaises(data_schema.SchemaError,
295 data_schema.try_get_reference,
296 "object:",
297 ctx,
298 self.empty_schema)
299
300 def test_empty_fragment(self):
301 ctx = data_schema.Context(None, root_object={"foo": "bar"}, settings=None)
302 r = data_schema.try_get_reference(
303 "object:#",
304 ctx,
305 self.empty_schema)
306 self.assertIs(r, ctx.root_object)
307 self.assertIs(r, ctx.current_object)
308
309 def test_point_fragment_with_root(self):
310 ctx = data_schema.Context(None, root_object={"foo": "bar"}, settings=None)
311 r = data_schema.try_get_reference(
312 "object:#.",
313 ctx,
314 self.empty_schema)
315 self.assertIs(r, ctx.root_object)
316 self.assertIs(r, ctx.current_object)
317
318 def test_point_fragment_with_current_object(self):
319 current_object = {
320 "current": {
321 "object": "value"}}
322 root_object = {"root": current_object}
323 ctx = data_schema.Context(None, current_object=current_object,
324 root_object=root_object, settings=None)
325 r = data_schema.try_get_reference(
326 "object:#.",
327 ctx,
328 self.empty_schema)
329 self.assertIs(r, ctx.current_object)
330 self.assertIs(r, current_object)
331 self.assertIsNot(r, ctx.root_object)
332
333 r = data_schema.try_get_reference(
334 "object:#.current",
335 ctx,
336 self.empty_schema)
337 self.assertEqual({"object": "value"}, r)
338
339 r = data_schema.try_get_reference(
340 "object:#.current.object",
341 ctx,
342 self.empty_schema)
343 self.assertEqual("value", r)
344
345 def test_point_fragment_with_invalid_current_object_refs(self):
346 current_object = {
347 "current": {
348 "object": "value"}}
349 root_object = {"root": current_object}
350 ctx = data_schema.Context(None, current_object=current_object,
351 root_object=root_object, settings=None)
352 r = data_schema.try_get_reference(
353 "object:#.",
354 ctx,
355 self.empty_schema)
356 self.assertIs(r, ctx.current_object)
357 self.assertIs(r, current_object)
358
359 r = data_schema.try_get_reference(
360 "object:#.non-current",
361 ctx,
362 self.empty_schema)
363 self.assertIsNone(r)
364
365 r = data_schema.try_get_reference(
366 "object:#.non-current.object", ctx, self.empty_schema)
367 self.assertIsNone(r)
368
369 r = data_schema.try_get_reference(
370 "object:#.current.non-object", ctx, self.empty_schema)
371 self.assertIsNone(r)
372
373 self.assertRaises(
374 data_schema.SchemaError,
375 data_schema.try_get_reference,
376 "object:#.current..",
377 ctx,
378 self.empty_schema)
379
380 self.assertRaises(
381 TypeError,
382 data_schema.try_get_reference,
383 "object:#..current.object",
384 ctx,
385 self.empty_schema)
386
387 def test_fragment_with_current_object_and_root(self):
388 current_object = {
389 "current": {
390 "object": "value"}}
391 root_object = {"root": current_object}
392 ctx = data_schema.Context(None, current_object=current_object,
393 root_object=root_object, settings=None)
394 r = data_schema.try_get_reference(
395 "object:#", ctx, self.empty_schema)
396 self.assertIs(r, ctx.root_object)
397 self.assertIs(r, root_object)
398
399 def test_default_schema_ref(self):
400 ctx = data_schema.Context(None, root_object={"foo": "bar"},
401 settings=None)
402 r = data_schema.try_get_reference("#foo", ctx, self.empty_schema)
403 self.assertEqual("bar", r)
404 r = data_schema.try_get_reference("#bar", ctx, self.empty_schema)
405 self.assertIsNone(r)
406 sentinel = object()
407 r = data_schema.try_get_reference("#bar", ctx, self.empty_schema,
408 default=sentinel)
409 self.assertIs(r, sentinel)
410
411 def test_object_schema_ref(self):
412 ctx = data_schema.Context(None, root_object={"foo": "bar"},
413 settings=None)
414 r = data_schema.try_get_reference("object:#foo", ctx,
415 self.empty_schema)
416 self.assertEqual("bar", r)
417 r = data_schema.try_get_reference("object:#bar", ctx,
418 self.empty_schema)
419 self.assertIsNone(r)
420 sentinel = object()
421 r = data_schema.try_get_reference(
422 "object:#bar",
423 ctx,
424 self.empty_schema,
425 default=sentinel)
426 self.assertIs(r, sentinel)
427
428 def test_nested_keys(self):
429 sentinel = object()
430 ctx = data_schema.Context(
431 None,
432 root_object={"foo": "bar",
433 "k1": {"k2": "v2",
434 "k3": None},
435 "k4": None,
436 "k5": [1, 2, 3]},
437 settings=None)
438 r = data_schema.try_get_reference(
439 "#k1.k2", ctx, self.empty_schema)
440 self.assertEqual("v2", r)
441 r = data_schema.try_get_reference(
442 "#k1.k3", ctx, self.empty_schema)
443 self.assertIsNone(r)
444 r = data_schema.try_get_reference(
445 "#k1.k3.fornone", ctx, self.empty_schema)
446 self.assertIsNone(r)
447 r = data_schema.try_get_reference(
448 "#k1.k3.fornone", ctx, self.empty_schema, default=sentinel)
449 self.assertIs(r, sentinel)
450 r = data_schema.try_get_reference(
451 "#k5.0", ctx, self.empty_schema, default=sentinel)
452 self.assertIs(r, sentinel)
453 r = data_schema.try_get_reference(
454 "#k6", ctx, self.empty_schema, default=sentinel)
455 self.assertIs(r, sentinel)
456
457 def test_url_quoted_fragment(self):
458 ctx = data_schema.Context(
459 None,
460 root_object={"foo": "bar",
461 "k1": {"k2": "v2",
462 "k3": None},
463 "k4": None,
464 "k5": [1, 2, 3]},
465 settings=None)
466 r = data_schema.try_get_reference(
467 "#fo%6F", ctx, self.empty_schema)
468 self.assertEqual("bar", r)
469
470 def test_no_duplicate_unquoting_in_fragment(self):
471 ctx = data_schema.Context(
472 None,
473 root_object={"fo%o": "bar"},
474 settings=None)
475 r = data_schema.try_get_reference(
476 "#fo%25o", ctx, self.empty_schema)
477 self.assertEqual("bar", r)
478
479 def test_schema_ref_must_have_fragment(self):
480 ctx = data_schema.Context(None, root_schema={"foo": "bar"}, settings=None)
481 self.assertRaises(
482 data_schema.SchemaError,
483 data_schema.try_get_reference,
484 "schema:",
485 ctx,
486 self.empty_schema)
487
488 def test_schema_ref_must_have_absolute_fragment(self):
489 ctx = data_schema.Context(None, root_schema={"foo": "bar"}, settings=None)
490 self.assertRaises(
491 data_schema.SchemaError,
492 data_schema.try_get_reference,
493 "schema:#",
494 ctx,
495 self.empty_schema)
496
497 def test_schema_ref_root_schema(self):
498 schema = data_schema._Schema(
499 None, True, {"foo": "bar"})
500 ctx = data_schema.Context(None, root_schema=schema, settings=None)
501 r = data_schema.try_get_reference(
502 "schema:#/", ctx, schema)
503 self.assertIs(r, schema)
504
505 def test_unknown_schema_ref_yet(self):
506 ctx = data_schema.Context(None, root_object={"foo": "bar"}, settings=None)
507 self.assertRaises(
508 data_schema.SchemaError,
509 data_schema.try_get_reference,
510 "data:#",
511 ctx,
512 self.empty_schema)
513
514 def test_schema_not_found(self):
515 sentinel = object()
516 root_schema = data_schema._Schema(None, True, {"foo": "bar"})
517 ctx = data_schema.Context(None, root_schema=root_schema,
518 settings=None)
519 r = data_schema.try_get_reference(
520 "schema:#/foo/bar", ctx, root_schema, default=sentinel)
521 self.assertIs(r, sentinel)
522 r = data_schema.try_get_reference(
523 "schema:#/foo2", ctx, root_schema, default=sentinel)
524 self.assertIs(r, sentinel)
525 r = data_schema.try_get_reference(
526 "schema:#/foo3", ctx, root_schema)
527 self.assertIsNone(r)
528
529 def test_schema_is_found(self):
530 subsubschema = {"foo3": "bar3"}
531 subschema = {"foo2": subsubschema}
532 schema = data_schema._Schema(None, True, {"foo": subschema})
533 ctx = data_schema.Context(None, root_schema=schema, settings=None)
534 r = data_schema.try_get_reference(
535 "schema:#/foo/foo2", ctx, schema)
536 self.assertEqual(subsubschema, r)
537
538 def test_schema_with_trailing_slash_is_found(self):
539 subsubschema = {"foo3": "bar3"}
540 subschema = {"foo2": subsubschema}
541 schema = data_schema._Schema(None, True, {"foo": subschema})
542 ctx = data_schema.Context(None, root_schema=schema, settings=None)
543 r = data_schema.try_get_reference(
544 "schema:#/foo/foo2/", ctx, schema)
545 self.assertIsNone(r)
546
547 def test_schema_is_found_with_quoted_fragment(self):
548 subsubschema = {"foo3": "bar3"}
549 subschema = {"foo2": subsubschema}
550 schema = data_schema._Schema(None, True, {"foo": subschema})
551 ctx = data_schema.Context(None, root_schema=schema, settings=None)
552 r = data_schema.try_get_reference(
553 "schema:#/f%6Fo/foo%32", ctx, schema)
554 self.assertEqual(subsubschema, r)
555
556
557 class SchemaConditionals(unittest.TestCase):
558
559 def setUp(self):
560 self._ctx = data_schema.Context(
561 None, root_object={"foo": "bar", "foo2": None}, settings=None)
562
563 def test_no_cond(self):
564 schema = data_schema._Schema(None, True, {"type": None})
565 self.assertIs(data_schema.process_schema_conditionals(
566 schema, self._ctx),
567 schema)
568
569 def test_cond_is_none(self):
570 schema = data_schema._Schema(None, True, {"type": None,
571 "cond": None})
572 self.assertIs(data_schema.process_schema_conditionals(
573 schema, self._ctx),
574 schema)
575
576 def test_ambiguous(self):
577 schema = data_schema._Schema(None, True, {"type": None,
578 "cond": None,
579 "match": None})
580 self.assertRaises(
581 data_schema.SchemaError,
582 data_schema.process_schema_conditionals,
583 schema,
584 self._ctx)
585
586 def test_cond_not_a_sequence(self):
587 schema = data_schema._Schema(None, True, {"type": None,
588 "cond": {"type": None}})
589 self.assertRaises(
590 data_schema.SchemaError,
591 data_schema.process_schema_conditionals,
592 schema,
593 self._ctx)
594
595 def test_match_not_a_sequence(self):
596 schema = data_schema._Schema(
597 None, True, {"type": None,
598 "match": {"type": None}})
599 self.assertRaises(
600 data_schema.SchemaError,
601 data_schema.process_schema_conditionals,
602 schema,
603 self._ctx)
604
605 def test_condline_not_a_dict(self):
606 schema = data_schema._Schema(None, True, {"type": None,
607 "cond": [None]})
608 self.assertRaises(
609 data_schema.SchemaError,
610 data_schema.process_schema_conditionals,
611 schema,
612 self._ctx)
613
614 def test_matchline_not_a_dict(self):
615 schema = {"type": None,
616 "match": [None]}
617 self.assertRaises(
618 data_schema.SchemaError,
619 data_schema.process_schema_conditionals,
620 schema,
621 self._ctx)
622
623 def test_cond_unknown_predicate(self):
624 schema = data_schema._Schema(
625 None, True, {"type": None,
626 "cond": [
627 {"unexisting-when-xxxx": None,
628 "then": {}}
629 ]})
630 self.assertRaises(
631 data_schema.SchemaError,
632 data_schema.process_schema_conditionals,
633 schema,
634 self._ctx)
635
636 def test_match_unknown_predicate(self):
637 schema = data_schema._Schema(
638 None, True, {"type": None,
639 "match": [
640 {"unexisting-when-xxxx": None,
641 "then": {}}
642 ]})
643 self.assertRaises(
644 data_schema.SchemaError,
645 data_schema.process_schema_conditionals,
646 schema,
647 self._ctx)
648
649 def test_simple_replace_when_true(self):
650 schema = data_schema._Schema(
651 None, True, {"type": None,
652 "require": ["huhu", "haha"],
653 "cond": [
654 {"when": True,
655 "then": {
656 "require": ["r1", "r2", "r3"],
657 "new-key": None,
658 }}
659 ]})
660 r = data_schema.process_schema_conditionals(schema, self._ctx)
661 self.assertIsNot(r, schema)
662 self.assertEqual(["r1", "r2", "r3"], r["require"])
663 self.assertTrue("new-key" in r)
664 self.assertIsNone(r["new-key"])
665 self.assertFalse("cond" in r)
666
667 def test_simple_replace_when_not_false(self):
668 schema = data_schema._Schema(
669 None, True, {"type": None,
670 "require": ["huhu", "haha"],
671 "cond": [
672 {"when": {"not": False},
673 "then": {
674 "require": ["r1", "r2", "r3"],
675 "new-key": None,
676 }}
677 ]})
678 r = data_schema.process_schema_conditionals(schema, self._ctx)
679 self.assertIsNot(r, schema)
680 self.assertEqual(["r1", "r2", "r3"], r["require"])
681 self.assertTrue("new-key" in r)
682 self.assertIsNone(r["new-key"])
683 self.assertFalse("cond" in r)
684
685 def test_simple_merge_when_true(self):
686 schema = data_schema._Schema(
687 None, True, {"type": None,
688 "require": ["huhu", "haha"],
689 "old-key": "here I am",
690 "cond": [
691 {"when": True,
692 "then-merge": {
693 "require": ["r1", "r2", "r3"],
694 "new-key": None,
695 "old-key": "{{::DEL::}}"
696 }}
697 ]})
698 r = data_schema.process_schema_conditionals(schema, self._ctx)
699 self.assertIsNot(r, schema)
700 self.assertEqual(["huhu", "haha", "r1", "r2", "r3"], r["require"])
701 self.assertTrue("new-key" in r)
702 self.assertIsNone(r["new-key"])
703 self.assertFalse("old-key" in r)
704 self.assertFalse("cond" in r)
705
706 def test_simple_replace_first_wins_1(self):
707 schema = data_schema._Schema(
708 None, True, {"type": None,
709 "require": ["huhu", "haha", "hehe"],
710 "cond": [
711 {"when": True,
712 "then": {
713 "new-key2": "v2"}},
714 {"when": True,
715 "then": {
716 "require": ["r1", "r2", "r3"],
717 "new-key": None}}
718 ]})
719 r = data_schema.process_schema_conditionals(schema, self._ctx)
720 self.assertIsNot(r, schema)
721 self.assertEqual(["huhu", "haha", "hehe"], r["require"])
722 self.assertTrue("new-key2" in r)
723 self.assertEqual("v2", r["new-key2"])
724 self.assertFalse("cond" in r)
725
726 def test_simple_replace_first_wins_2(self):
727 schema = data_schema._Schema(
728 None, True, {"type": None,
729 "require": ["huhu", "haha", "hehe"],
730 "cond": [
731 {"when": False,
732 "then": {
733 "new-key2": "v2"}},
734 {"when": True,
735 "then": {
736 "require": ["r1", "r2", "r3"],
737 "new-key": None}}
738 ]})
739 r = data_schema.process_schema_conditionals(schema, self._ctx)
740 self.assertIsNot(r, schema)
741 self.assertEqual(["r1", "r2", "r3"], r["require"])
742 self.assertTrue("new-key" in r)
743 self.assertIsNone(r["new-key"])
744 self.assertFalse("new-key2" in r)
745 self.assertFalse("cond" in r)
746
747 def test_simple_replace_when_false(self):
748 schema = data_schema._Schema(
749 None, True, {"type": None,
750 "require": ["huhu", "haha"],
751 "cond": [
752 {"when": False,
753 "then": {
754 "require": ["r1", "r2", "r3"],
755 "new-key": None,
756 }}
757 ]})
758 r = data_schema.process_schema_conditionals(schema, self._ctx)
759 self.assertIsNot(r, schema)
760 self.assertEqual(["huhu", "haha"], r["require"])
761 self.assertFalse("new-key" in r)
762 self.assertFalse("cond" in r)
763
764 def test_simple_replace_when_ref_true(self):
765 schema = data_schema._Schema(
766 None, True, {"type": None,
767 "require": ["huhu", "haha"],
768 "cond": [
769 {"when-ref-true": '#foo',
770 "then": {
771 "require": ["r1", "r2", "r3"],
772 "new-key": None,
773 }}
774 ]})
775 r = data_schema.process_schema_conditionals(schema, self._ctx)
776 self.assertIsNot(r, schema)
777 self.assertEqual(["r1", "r2", "r3"], r["require"])
778 self.assertTrue("new-key" in r)
779 self.assertIsNone(r["new-key"])
780 self.assertFalse("cond" in r)
781
782 def test_simple_replace_when_ref_true_2(self):
783 schema = data_schema._Schema(
784 None, True, {"type": None,
785 "require": ["huhu", "haha"],
786 "cond": [
787 {"when": {"ref-true": '#foo'},
788 "then": {
789 "require": ["r1", "r2", "r3"],
790 "new-key": None,
791 }}
792 ]})
793 r = data_schema.process_schema_conditionals(schema, self._ctx)
794 self.assertIsNot(r, schema)
795 self.assertEqual(["r1", "r2", "r3"], r["require"])
796 self.assertTrue("new-key" in r)
797 self.assertIsNone(r["new-key"])
798 self.assertFalse("cond" in r)
799
800 def test_simple_replace_when_ref_is_not_true(self):
801 schema = data_schema._Schema(
802 None, True, {"type": None,
803 "require": ["huhu", "haha"],
804 "cond": [
805 {"when-ref-true": '#not-a-foo',
806 "then": {
807 "require": ["r1", "r2", "r3"],
808 "new-key": None,
809 }}
810 ]})
811 r = data_schema.process_schema_conditionals(schema, self._ctx)
812 self.assertIsNot(r, schema)
813 self.assertEqual(["huhu", "haha"], r["require"])
814 self.assertTrue("new-key" not in r)
815 self.assertFalse("cond" in r)
816
817 def test_simple_replace_when_ref_is_not_true_2(self):
818 schema = data_schema._Schema(
819 None, True, {"type": None,
820 "require": ["huhu", "haha"],
821 "cond": [
822 {"when": {"ref-true": '#not-a-foo'},
823 "then": {
824 "require": ["r1", "r2", "r3"],
825 "new-key": None,
826 }}
827 ]})
828 r = data_schema.process_schema_conditionals(schema, self._ctx)
829 self.assertIsNot(r, schema)
830 self.assertEqual(["huhu", "haha"], r["require"])
831 self.assertTrue("new-key" not in r)
832 self.assertFalse("cond" in r)
833
834 def test_simple_replace_when_ref_exists(self):
835 schema = data_schema._Schema(
836 None, True, {"type": None,
837 "require": ["huhu", "haha"],
838 "cond": [
839 {"when-ref-exists": '#foo2',
840 "then": {
841 "require": ["r1", "r2", "r3"],
842 "new-key": None,
843 }},
844 {"when": True,
845 "then": {
846 "new-key3": "val"}}
847 ]})
848 r = data_schema.process_schema_conditionals(schema, self._ctx)
849 self.assertIsNot(r, schema)
850 self.assertEqual(["r1", "r2", "r3"], r["require"])
851 self.assertTrue("new-key" in r)
852 self.assertIsNone(r["new-key"])
853 self.assertFalse("new-key3" in r)
854 self.assertFalse("cond" in r)
855
856 def test_simple_replace_when_ref_exists_2(self):
857 schema = data_schema._Schema(
858 None, True, {"type": None,
859 "require": ["huhu", "haha"],
860 "cond": [
861 {"when": {"ref-exists": '#foo2'},
862 "then": {
863 "require": ["r1", "r2", "r3"],
864 "new-key": None,
865 }},
866 {"when": True,
867 "then": {
868 "new-key3": "val"}}
869 ]})
870 r = data_schema.process_schema_conditionals(schema, self._ctx)
871 self.assertIsNot(r, schema)
872 self.assertEqual(["r1", "r2", "r3"], r["require"])
873 self.assertTrue("new-key" in r)
874 self.assertIsNone(r["new-key"])
875 self.assertFalse("new-key3" in r)
876 self.assertFalse("cond" in r)
877
878 def test_simple_replace_when_ref_exists_is_false(self):
879 schema = data_schema._Schema(
880 None, True, {"type": None,
881 "cond": [
882 {"when-ref-exists": '#foo-not-existing',
883 "then": {
884 "require": ["r1", "r2", "r3"],
885 "new-key": None,
886 }},
887 {"when": True,
888 "then": {
889 "new-key3": "val"}}
890 ]})
891 r = data_schema.process_schema_conditionals(schema, self._ctx)
892 self.assertIsNot(r, schema)
893 self.assertFalse("require" in r)
894 self.assertFalse("new-key" in r)
895 self.assertEqual("val", r["new-key3"])
896 self.assertFalse("cond" in r)
897
898 def test_simple_replace_when_ref_exists_is_false_2(self):
899 schema = data_schema._Schema(
900 None, True, {"type": None,
901 "cond": [
902 {"when": {"ref-exists": '#foo-not-existing'},
903 "then": {
904 "require": ["r1", "r2", "r3"],
905 "new-key": None,
906 }},
907 {"when": True,
908 "then": {
909 "new-key3": "val"}}
910 ]})
911 r = data_schema.process_schema_conditionals(schema, self._ctx)
912 self.assertIsNot(r, schema)
913 self.assertFalse("require" in r)
914 self.assertFalse("new-key" in r)
915 self.assertEqual("val", r["new-key3"])
916 self.assertFalse("cond" in r)
917
918 def test_allOf_true(self):
919 schema = data_schema._Schema(
920 None, True, {"cond": [
921 {"when": {"all-of": [
922 True,
923 {"ref-exists": '#foo2'},
924 {"ref-true": '#foo'}]},
925 "then": {"type": "string"}},
926 {"when": True,
927 "then": {"type": None}}
928 ]})
929 r = data_schema.process_schema_conditionals(schema, self._ctx)
930 self.assertIsNot(r, schema)
931 self.assertEqual("string", r["type"])
932
933 def test_allOf_false(self):
934 schema = data_schema._Schema(
935 None, True, {"cond": [
936 {"when": {"all-of": [
937 True,
938 {"ref-exists": '#foo-non-existing'},
939 {"ref-true": '#foo'}]},
940 "then": {"type": "string"}},
941 {"when": True,
942 "then": {"type": None}}
943 ]})
944 r = data_schema.process_schema_conditionals(schema, self._ctx)
945 self.assertIsNot(r, schema)
946 self.assertIsNone(r["type"])
947
948 def test_short_allOf_true(self):
949 schema = data_schema._Schema(
950 None, True, {"cond": [
951 {"when": [
952 True,
953 {"ref-exists": '#foo2'},
954 {"ref-true": '#foo'}],
955 "then": {"type": "string"}},
956 {"when": True,
957 "then": {"type": None}}
958 ]})
959 r = data_schema.process_schema_conditionals(schema, self._ctx)
960 self.assertIsNot(r, schema)
961 self.assertEqual("string", r["type"])
962
963 def test_short_allOf_false(self):
964 schema = data_schema._Schema(
965 None, True, {"cond": [
966 {"when": [
967 True,
968 {"ref-exists": '#foo-non-existing'},
969 {"ref-true": '#foo'}],
970 "then": {"type": "string"}},
971 {"when": True,
972 "then": {"type": None}}
973 ]})
974 r = data_schema.process_schema_conditionals(schema, self._ctx)
975 self.assertIsNot(r, schema)
976 self.assertIsNone(r["type"])
977
978 def test_anyOf_true(self):
979 schema = data_schema._Schema(
980 None, True, {"cond": [
981 {"when": {"any-of": [
982 False,
983 {"ref-exists": '#foo2'},
984 {"ref-true": '#foo'}]},
985 "then": {"type": "string"}},
986 {"when": True,
987 "then": {"type": None}}
988 ]})
989 r = data_schema.process_schema_conditionals(schema, self._ctx)
990 self.assertIsNot(r, schema)
991 self.assertEqual("string", r["type"])
992
993 def test_anyOf_false(self):
994 schema = data_schema._Schema(
995 None, True, {"cond": [
996 {"when": {"any-of": [
997 False,
998 {"ref-exists": '#foo2-non'},
999 {"ref-true": '#foo2'}]},
1000 "then": {"type": "string"}},
1001 {"when": True,
1002 "then": {"type": None}}
1003 ]})
1004 r = data_schema.process_schema_conditionals(schema, self._ctx)
1005 self.assertIsNot(r, schema)
1006 self.assertIsNone(r["type"])
1007
1008 def test_oneOf_true(self):
1009 schema = data_schema._Schema(
1010 None, True, {"cond": [
1011 {"when": {"one-of": [
1012 False,
1013 {"ref-exists": '#foo2'},
1014 {"not": {"ref-true": '#foo'}}]},
1015 "then": {"type": "string"}},
1016 {"when": True,
1017 "then": {"type": None}}
1018 ]})
1019 r = data_schema.process_schema_conditionals(schema, self._ctx)
1020 self.assertIsNot(r, schema)
1021 self.assertEqual("string", r["type"])
1022
1023 def test_oneOf_false(self):
1024 schema = data_schema._Schema(
1025 None, True, {"cond": [
1026 {"when": {"one-of": [
1027 False,
1028 {"ref-exists": '#foo2'},
1029 {"ref-true": '#foo'}]},
1030 "then": {"type": "string"}},
1031 {"when": True,
1032 "then": {"type": None}}
1033 ]})
1034 r = data_schema.process_schema_conditionals(schema, self._ctx)
1035 self.assertIsNot(r, schema)
1036 self.assertIsNone(r["type"])
1037
1038 def test_oneOf_false_2(self):
1039 schema = data_schema._Schema(
1040 None, True, {"cond": [
1041 {"when": {"one-of": [
1042 False,
1043 {"not": {"ref-exists": '#foo2'}},
1044 {"not": {"ref-true": '#foo'}}]},
1045 "then": {"type": "string"}},
1046 {"when": True,
1047 "then": {"type": None}}
1048 ]})
1049 r = data_schema.process_schema_conditionals(schema, self._ctx)
1050 self.assertIsNot(r, schema)
1051 self.assertIsNone(r["type"])
1052
1053 def test_match_nothing(self):
1054 schema = data_schema._Schema(
1055 None,
1056 True,
1057 {
1058 "match": [
1059 {"when": False,
1060 "then": {"new-key": None}},
1061 {"when": False,
1062 "then": {"new-key2": None}}
1063 ]})
1064 r = data_schema.process_schema_conditionals(schema, self._ctx)
1065 self.assertFalse("new-key" in r)
1066 self.assertFalse("new-key2" in r)
1067
1068 def test_match_all(self):
1069 schema = data_schema._Schema(
1070 None,
1071 True,
1072 {
1073 "match": [
1074 {"when": True,
1075 "then": {"new-key": "value"}},
1076 {"when": True,
1077 "then": {"new-key2": "value2"}}
1078 ]})
1079 r = data_schema.process_schema_conditionals(schema, self._ctx)
1080 self.assertEqual("value", r["new-key"])
1081 self.assertEqual("value2", r["new-key2"])
1082
1083 def test_match_some(self):
1084 schema = data_schema._Schema(
1085 None,
1086 True,
1087 {
1088 "match": [
1089 {"when": True,
1090 "then": {"new-key": "value"}},
1091 {"when": False,
1092 "then": {"new-key2": "value2"}},
1093 {"when": True,
1094 "then": {"new-key3": "value3"}},
1095 {"when": False,
1096 "then": {"new-key4": "value4"}}
1097 ]})
1098 r = data_schema.process_schema_conditionals(schema, self._ctx)
1099 self.assertEqual("value", r["new-key"])
1100 self.assertFalse("new-key2" in r)
1101 self.assertEqual("value3", r["new-key3"])
1102 self.assertFalse("new-key4" in r)
1103
1104 def test_match_some_merge(self):
1105 schema = data_schema._Schema(
1106 None,
1107 True,
1108 {"match": [
1109 {"when": True,
1110 "then": {"new-key": [1, 2]}},
1111 {"when": False,
1112 "then": {"new-key2": "value2"}},
1113 {"when": True,
1114 "then-merge": {"new-key": ["value3"]}},
1115 {"when": False,
1116 "then": {"new-key3": "value3"}}
1117 ]})
1118 r = data_schema.process_schema_conditionals(schema, self._ctx)
1119 self.assertEqual([1, 2, "value3"], r["new-key"])
1120 self.assertFalse("new-key2" in r)
1121 self.assertFalse("new-key3" in r)
1122
1123 def test_match_some_replace(self):
1124 schema = data_schema._Schema(
1125 None,
1126 True,
1127 {"match": [
1128 {"when": True,
1129 "then": {"new-key": [1, 2]}},
1130 {"when": False,
1131 "then": {"new-key2": "value2"}},
1132 {"when": True,
1133 "then-replace": {"new-key": ["value3"]}},
1134 {"when": True,
1135 "then": {"new-key3": "value3"}}
1136 ]})
1137 r = data_schema.process_schema_conditionals(schema, self._ctx)
1138 self.assertEqual(["value3"], r["new-key"])
1139 self.assertFalse("new-key2" in r)
1140 self.assertEqual("value3", r["new-key3"])
1141
1142 def test_match_some_merge_existing(self):
1143 # the typical case within vlobby: just extend "required"
1144 schema = data_schema._Schema(
1145 None, True, {"required": [1, 2],
1146 "match": [
1147 {"when": True,
1148 "then": {"required": [3, 4]}},
1149 {"when": False,
1150 "then": {"required": [0]}},
1151 {"when": True,
1152 "then-merge": {"required": [5, 6, 7]}},
1153 {"when": True,
1154 "then-merge": {"required": [4, 8]}}
1155 ]})
1156 r = data_schema.process_schema_conditionals(schema, self._ctx)
1157 self.assertEqual([3, 4, 5, 6, 7, 4, 8], r["required"])
1158
1159 def test_equal_ref_and_value(self):
1160 schema = data_schema._Schema(
1161 None, True, {"foos": "bar",
1162 "match": [{
1163 "when": {
1164 "equals": [
1165 {"ref": "object:#foo"},
1166 {"value": "bar"}]},
1167 "then-replace": {
1168 "foos": "new-bar"}}]
1169 })
1170 r = data_schema.process_schema_conditionals(schema, self._ctx)
1171 self.assertEqual("new-bar", r["foos"])
1172
1173 def test_equal_val_and_ref(self):
1174 schema = data_schema._Schema(
1175 None, True, {"foos": "bar",
1176 "cond": [{
1177 "when": {
1178 "equals": [
1179 {"val": "bar"},
1180 {"ref": "object:#foo"}]},
1181 "then-replace": {
1182 "foos": "new-bar"}}]
1183 })
1184 r = data_schema.process_schema_conditionals(schema, self._ctx)
1185 self.assertEqual("new-bar", r["foos"])
1186
1187 def test_equal_no_list(self):
1188 schema = data_schema._Schema(
1189 None, True, {"foos": "bar",
1190 "match": [{
1191 "when": {
1192 "equals": {"type": None},
1193 "then-replace": {
1194 "foos": "new-bar"}}}]
1195 })
1196 self.assertRaises(
1197 data_schema.SchemaError,
1198 data_schema.process_schema_conditionals,
1199 schema,
1200 self._ctx)
1201
1202 def test_equal_list_length_mismatch_1(self):
1203 schema = data_schema._Schema(
1204 None, True, {"foo": "bar",
1205 "match": [{
1206 "when": {
1207 "equals": [
1208 {"ref": "object:#foo"}]},
1209 "then-replace": {
1210 "foo": "new-bar"}}]
1211 })
1212 self.assertRaises(
1213 data_schema.SchemaError,
1214 data_schema.process_schema_conditionals,
1215 schema,
1216 self._ctx)
1217
1218 def test_equal_list_length_mismatch_3(self):
1219 schema = data_schema._Schema(
1220 None, True, {"foo": "bar",
1221 "match": [{
1222 "when": {
1223 "equals": [
1224 {"ref": "object:#foo"},
1225 {"ref": "object:#foo"},
1226 {"ref": "object:#foo"}]},
1227 "then-replace": {
1228 "foo": "new-bar"}}]
1229 })
1230 self.assertRaises(
1231 data_schema.SchemaError,
1232 data_schema.process_schema_conditionals,
1233 schema,
1234 self._ctx)
1235
1236 def test_raise_if_scheme_ref_is_not_the_single_key(self):
1237 schema = data_schema._Schema(
1238 None, True, {"$ref": "schema:#/",
1239 "type": None
1240 })
1241 ctx = data_schema.Context(
1242 None, root_schema=schema, settings=None)
1243 self.assertRaises(
1244 data_schema.SchemaError,
1245 data_schema.process_schema_references,
1246 schema,
1247 ctx)
1248
1249 def test_raise_if_scheme_ref_is_not_the_single_key_root(self):
1250 schema = data_schema._Schema(
1251 None, True, {"$ref": "schema:#/subschema",
1252 "subschema": {
1253 "type": None
1254 }
1255 })
1256 ctx = data_schema.Context(
1257 None, root_schema=schema, settings=None)
1258 r = data_schema.process_schema_references(
1259 schema,
1260 ctx,
1261 check_single_ref_key=False)
1262 self.assertEqual({"type": None}, r)
1263
1264 def test_recursive_schema_scheme(self):
1265 barschema = {
1266 "type": "null"
1267 }
1268 fooschema = {
1269 "$ref": "schema:#/bar"
1270 }
1271 schema = data_schema._Schema(
1272 None, True, {"foo": fooschema,
1273 "bar": barschema,
1274 "$ref": "schema:#/foo"
1275 })
1276 ctx = data_schema.Context(
1277 None, root_schema=schema, settings=None)
1278 r = data_schema.process_schema_references(
1279 schema,
1280 ctx,
1281 check_single_ref_key=False)
1282 self.assertEqual({"type": "null"}, r)
1283
1284 def test_recursive_schema_scheme_raises_if_non_root_is_not_single_key(self):
1285 barschema = {
1286 "type": "null"
1287 }
1288 fooschema = {
1289 "$ref": "schema:#/bar",
1290 "type": "dict",
1291 }
1292 schema = data_schema._Schema(
1293 None, True, {
1294 "foo": fooschema,
1295 "bar": barschema,
1296 "$ref": "schema:#/foo"
1297 })
1298 ctx = data_schema.Context(
1299 None, root_schema=schema, settings=None)
1300 self.assertRaises(
1301 data_schema.SchemaError,
1302 data_schema.process_schema_references,
1303 schema,
1304 ctx,
1305 check_single_ref_key=False)
1306
1307 def test_recursive_schema_scheme_ref_to_non_existing_schema_raises(self):
1308 barschema = {
1309 "type": "null"
1310 }
1311 fooschema = {
1312 "$ref": "schema:#/non-bar",
1313 }
1314 schema = data_schema._Schema(
1315 None, True, {
1316 "foo": fooschema,
1317 "bar": barschema,
1318 "$ref": "schema:#/foo"
1319 })
1320 ctx = data_schema.Context(
1321 None, root_schema=schema, settings=None)
1322 self.assertRaises(
1323 data_schema.SchemaError,
1324 data_schema.process_schema_references,
1325 schema,
1326 ctx,
1327 check_single_ref_key=False)
1328
1329
1330 class BasicValidation(unittest.TestCase):
1331
1332 def test_schema_must_be_a_dict_alike(self):
1333 try:
1334 pr = list(data_schema.validate(None, None))
1335 except data_schema.SchemaError:
1336 pass
1337 else:
1338 self.assertFalse(
1339 "no SchemaError raised when a non-dict given as schema")
1340
1341 def test_problem_ctor_nonexisting_code(self):
1342 self.assertRaises(ValueError, data_schema.ValidationProblem, code=2)
1343
1344 def test_problem_ctor_no_code(self):
1345 self.assertRaises(TypeError, data_schema.ValidationProblem, code=None)
1346
1347 def test_error_ctor(self):
1348 v = data_schema.ValidationProblem(code=10000)
1349 self.assertEqual(data_schema.ERROR, v.severity)
1350
1351 def test_warning_ctor(self):
1352 v = data_schema.ValidationProblem(code=80000)
1353 self.assertEqual(data_schema.WARNING, v.severity)
1354
1355 def test_d1(self):
1356 x = list(data_schema.validate({}, {"type": "dict"}))
1357 self.assertEqual(0, len(x))
1358
1359 def test_d1_not_nullable(self):
1360 x = list(data_schema.validate(None, {"type": "dict"}))
1361 self.assertEqual(1, len(x))
1362 self.assertEqual(10000, x[0].code)
1363
1364 def test_d1_nullable(self):
1365 x = list(data_schema.validate(None, {"type": "dict",
1366 "nullable": True}))
1367 self.assertEqual(0, len(x))
1368
1369 def test_d2(self):
1370 x = list(data_schema.validate([], {"type": "map"}))
1371 self.assertEqual(1, len(x))
1372 self.assertEqual(data_schema.ERROR, x[0].severity)
1373 self.assertEqual(10000, x[0].code)
1374
1375 def test_d3(self):
1376 x = list(data_schema.validate(
1377 {"key": "value"},
1378 {"type": "dict",
1379 "required": ["key2"]}))
1380 self.assertEqual(2, len(x))
1381 self.assertEqual(data_schema.ERROR, x[0].severity)
1382 self.assertEqual(10004, x[0].code)
1383 self.assertEqual("key", x[0].hint)
1384 self.assertEqual(data_schema.ERROR, x[1].severity)
1385 self.assertEqual(10005, x[1].code)
1386 self.assertEqual(["key2"], x[1].hint)
1387
1388 def test_d4(self):
1389 x = list(data_schema.validate(
1390 {"key": "value"},
1391 {"type": "dict",
1392 "keys": {
1393 "key": {"type": "string"},
1394 },
1395 "required": ["key"]}))
1396 self.assertEqual(0, len(x))
1397
1398 def test_d5(self):
1399 x = list(data_schema.validate(
1400 {"key": "value"},
1401 {"type": "dict",
1402 "additionalKeys": False}))
1403 self.assertEqual(1, len(x))
1404 self.assertEqual(10004, x[0].code)
1405 self.assertEqual("key", x[0].hint)
1406
1407 def test_d5_2(self):
1408 x = list(data_schema.validate(
1409 {"key": "value"},
1410 {"type": "dict",
1411 "additionalKeys": False},
1412 skip_keys=["key"]))
1413 self.assertEqual(0, len(x))
1414
1415 def test_d5_3(self):
1416 x = list(data_schema.validate(
1417 {"key": "value",
1418 "key2": "value"},
1419 {"type": "dict",
1420 "additionalKeys": False},
1421 skip_keys=[re.compile(r"\Akey\d*\Z")]))
1422 self.assertEqual(0, len(x))
1423
1424 def test_d5_4(self):
1425 x = list(data_schema.validate(
1426 {"key": "value",
1427 "key2": "value"},
1428 {"type": "dict",
1429 "additionalKeys": False},
1430 skip_keys=[re.compile(r"\A__.+"), re.compile(r"\Akey\d+\Z")]))
1431 self.assertEqual(1, len(x))
1432 self.assertEqual(10004, x[0].code)
1433 self.assertEqual("key", x[0].hint)
1434
1435 def test_d6(self):
1436 x = list(data_schema.validate(
1437 {"key": "value"},
1438 {"type": "dict",
1439 "additionalKeys": True}))
1440 self.assertEqual(0, len(x))
1441
1442 def test_d7(self):
1443 x = list(data_schema.validate(
1444 {"key": "value"},
1445 {"type": "dict",
1446 "additionalKeys": {
1447 "type": "string"}}))
1448 self.assertEqual(0, len(x))
1449
1450 def test_d8(self):
1451 x = list(data_schema.validate(
1452 {"key": 1234},
1453 {"type": "dict",
1454 "additionalKeys": {
1455 "type": "string"}}))
1456 self.assertEqual(1, len(x))
1457 self.assertEqual(10002, x[0].code)
1458 self.assertEqual(1234, x[0].hint)
1459
1460 def test_d8_2(self):
1461 x = list(data_schema.validate(
1462 {"key": 1234},
1463 {"type": "dict",
1464 "additionalKeys": {
1465 "type": "string"}},
1466 skip_keys=["key"]))
1467 self.assertEqual(0, len(x))
1468
1469 def test_d9_non_string_keys(self):
1470 pr = list(data_schema.validate(
1471 {0: "value"},
1472 {"type": "dict",
1473 "additionalKeys": True}))
1474 self.assertEqual(1, len(pr))
1475 self.assertEqual(10003, pr[0].code)
1476
1477 def test_d10_int_dict_keys(self):
1478 pr = list(data_schema.validate(
1479 {1: "value", 2: "value2"},
1480 {"type": "dict",
1481 "keys": {
1482 1: {"type": "string"}},
1483 "additionalKeys": True,
1484 "keyNames": {"type": "int"}}))
1485 self.assertEqual(0, len(pr))
1486
1487 def test_error_message(self):
1488 self.assertEqual("dict expected",
1489 data_schema.problem_message(10000))
1490 pr = data_schema.ValidationProblem(code=10000)
1491 self.assertEqual("dict expected", data_schema.problem_message(pr))
1492
1493 self.assertEqual("duplicate dict key",
1494 data_schema.problem_message(80000))
1495 pr = data_schema.ValidationProblem(code=80000)
1496 self.assertEqual("duplicate dict key",
1497 data_schema.problem_message(pr))
1498
1499 self.assertRaises(KeyError, data_schema.problem_message, 1234)
1500
1501 def test_str_enum(self):
1502 pr = list(data_schema.validate(
1503 "e1",
1504 {"type": "string",
1505 "enum": ["e1", "e2"]}))
1506 self.assertEqual(0, len(pr))
1507
1508 pr = list(data_schema.validate(
1509 "e2",
1510 {"type": "string",
1511 "enum": ["e1", "e2"]}))
1512 self.assertEqual(0, len(pr))
1513
1514 def test_str_not_in_enum(self):
1515 pr = list(data_schema.validate(
1516 "e3",
1517 {"type": "string",
1518 "enum": ["e1", "e2"]}))
1519 self.assertEqual(1, len(pr))
1520 self.assertEqual(10043, pr[0].code)
1521
1522 def test_str_minlen(self):
1523 pr = list(data_schema.validate(
1524 "",
1525 {"type": "string",
1526 "minLength": 0}))
1527 self.assertEqual(0, len(pr))
1528
1529 pr = list(data_schema.validate(
1530 "",
1531 {"type": "string",
1532 "minLength": 1}))
1533 self.assertEqual(1, len(pr))
1534 self.assertEqual(10006, pr[0].code)
1535
1536 pr = list(data_schema.validate(
1537 "x",
1538 {"type": "string",
1539 "minLength": 1}))
1540 self.assertEqual(0, len(pr))
1541
1542 def test_str_maxlen(self):
1543 pr = list(data_schema.validate(
1544 "",
1545 {"type": "string",
1546 "maxLength": 0}))
1547 self.assertEqual(0, len(pr))
1548
1549 pr = list(data_schema.validate(
1550 "x",
1551 {"type": "string",
1552 "maxLength": 0}))
1553 self.assertEqual(1, len(pr))
1554 self.assertEqual(10007, pr[0].code)
1555
1556 pr = list(data_schema.validate(
1557 "x",
1558 {"type": "string",
1559 "maxLength": 1}))
1560 self.assertEqual(0, len(pr))
1561
1562 pr = list(data_schema.validate(
1563 b"x",
1564 {"type": "string",
1565 "maxLength": 1}))
1566 self.assertEqual(1, len(pr))
1567 self.assertEqual(10002, pr[0].code)
1568
1569 @staticmethod
1570 def _pattern_check_function(obj, schema, context=None):
1571 if obj == " 5 ":
1572 yield data_schema.ValidationProblem(code=10009)
1573
1574 def test_str_re(self):
1575 pr = list(data_schema.validate(
1576 "abc",
1577 {"type": "string",
1578 "pattern": r'\A[0-9]+\Z'}))
1579 self.assertEqual(1, len(pr))
1580 self.assertEqual(10008, pr[0].code)
1581
1582 pr = list(data_schema.validate(
1583 "123",
1584 {"type": "string",
1585 "pattern": re.compile(r'\A[a-z]+\Z')}))
1586 self.assertEqual(1, len(pr))
1587 self.assertEqual(10008, pr[0].code)
1588
1589 pr = list(data_schema.validate(
1590 "123",
1591 {"type": "string",
1592 "pattern": self._pattern_check_function}))
1593 self.assertEqual(0, len(pr))
1594
1595 pr = list(data_schema.validate(
1596 " 5 ",
1597 {"type": "string",
1598 "pattern": self._pattern_check_function}))
1599 self.assertEqual(1, len(pr))
1600 self.assertEqual(10009, pr[0].code)
1601
1602 def test_binary_basic(self):
1603 pr = list(data_schema.validate(
1604 b"",
1605 {"type": "binary"}))
1606 self.assertEqual(0, len(pr))
1607
1608 def test_str_is_not_binary(self):
1609 pr = list(data_schema.validate(
1610 "",
1611 {"type": "binary"}))
1612 self.assertEqual(1, len(pr))
1613 self.assertEqual(10035, pr[0].code)
1614
1615 @staticmethod
1616 def _binary_pattern_check_function(obj, schema, context=None):
1617 if obj != b"\x00":
1618 yield data_schema.ValidationProblem(code=10009)
1619
1620 def test_binary_pattern_check(self):
1621 pr = list(data_schema.validate(
1622 b"\x00",
1623 {"type": "binary",
1624 "pattern": self._binary_pattern_check_function}))
1625 self.assertEqual(0, len(pr))
1626
1627 pr = list(data_schema.validate(
1628 b"\x01",
1629 {"type": "binary",
1630 "pattern": self._binary_pattern_check_function}))
1631 self.assertEqual(1, len(pr))
1632 self.assertEqual(10009, pr[0].code)
1633
1634 def test_binary_re_str_match(self):
1635 pr = list(data_schema.validate(
1636 b"\x00\x00\x00",
1637 {"type": "binary",
1638 "pattern": u"\\x00+"}))
1639 self.assertEqual(0, len(pr))
1640
1641 def test_binary_re_bytes_match(self):
1642 pr = list(data_schema.validate(
1643 b"\x00\x00\x00",
1644 {"type": "binary",
1645 "pattern": b"\x00+"}))
1646 self.assertEqual(0, len(pr))
1647
1648 def test_binary_re_str_mismatch(self):
1649 pr = list(data_schema.validate(
1650 b"\x00\x00\x00",
1651 {"type": "binary",
1652 "pattern": u"\\x01+"}))
1653 self.assertEqual(1, len(pr))
1654 self.assertEqual(10047, pr[0].code)
1655
1656 def test_binary_re_bytes_mismatch(self):
1657 pr = list(data_schema.validate(
1658 b"\x00\x00\x00",
1659 {"type": "binary",
1660 "pattern": b"\x01+"}))
1661 self.assertEqual(1, len(pr))
1662 self.assertEqual(10047, pr[0].code)
1663
1664 def test_binary_length(self):
1665 pr = list(data_schema.validate(
1666 b"",
1667 {"type": "binary",
1668 "minLength": 1}))
1669 self.assertEqual(1, len(pr))
1670 self.assertEqual(10036, pr[0].code)
1671
1672 pr = list(data_schema.validate(
1673 b"1",
1674 {"type": "binary",
1675 "maxLength": 0}))
1676 self.assertEqual(1, len(pr))
1677 self.assertEqual(10037, pr[0].code)
1678
1679 def test_deny(self):
1680 pr = list(data_schema.validate("abc", {"type": "deny"}))
1681 self.assertEqual(1, len(pr))
1682 self.assertEqual(10010, pr[0].code)
1683
1684 def test_accept(self):
1685 pr = list(data_schema.validate("abc", {"type": "accept"}))
1686 self.assertEqual(0, len(pr))
1687
1688 pr = list(data_schema.validate(None, {"type": "accept"}))
1689 self.assertEqual(0, len(pr))
1690
1691 def test_null(self):
1692 pr = list(data_schema.validate(None, {"type": "none"}))
1693 self.assertEqual(0, len(pr))
1694
1695 pr = list(data_schema.validate(None, {"type": "null"}))
1696 self.assertEqual(0, len(pr))
1697
1698 pr = list(data_schema.validate(None, {"type": "nil"}))
1699 self.assertEqual(0, len(pr))
1700
1701 pr = list(data_schema.validate(None, {"type": None}))
1702 self.assertEqual(0, len(pr))
1703
1704 pr = list(data_schema.validate({}, {"type": None}))
1705 self.assertEqual(1, len(pr))
1706 self.assertEqual(10011, pr[0].code)
1707
1708 def test_l1(self):
1709 pr = list(data_schema.validate([], {"type": "list"}))
1710 self.assertEqual(0, len(pr))
1711
1712 pr = list(data_schema.validate(tuple(), {"type": "list"}))
1713 self.assertEqual(0, len(pr))
1714
1715 def test_l1_not_nullable(self):
1716 pr = list(data_schema.validate(None, {"type": "list"}))
1717 self.assertEqual(1, len(pr))
1718 self.assertEqual(10001, pr[0].code)
1719
1720 def test_l1_nullable(self):
1721 pr = list(data_schema.validate(
1722 None, {"type": "list", "nullable": True}))
1723 self.assertEqual(0, len(pr))
1724
1725 def test_l2_default_schema_for_items_is_deny(self):
1726 pr = list(data_schema.validate(["a", "b", "c"], {"type": "list"}))
1727 self.assertEqual(3, len(pr))
1728 for i in range(0, 3):
1729 self.assertEqual(10010, pr[i].code)
1730
1731 def test_l3_schema_for_items(self):
1732 pr = list(data_schema.validate(
1733 ["a", "b", "c"],
1734 {"type": "array",
1735 "items": {"type": "string"}}))
1736 self.assertEqual(0, len(pr))
1737
1738 def test_t1(self):
1739 pr = list(data_schema.validate([], {"type": "tuple"}))
1740 self.assertEqual(0, len(pr))
1741
1742 pr = list(data_schema.validate(tuple(), {"type": "tuple"}))
1743 self.assertEqual(0, len(pr))
1744
1745 def test_t1_not_nullable(self):
1746 pr = list(data_schema.validate(None, {"type": "tuple"}))
1747 self.assertEqual(1, len(pr))
1748 self.assertEqual(10014, pr[0].code)
1749
1750 def test_t1_nullable(self):
1751 pr = list(data_schema.validate(
1752 None, {"type": "tuple", "nullable": True}))
1753 self.assertEqual(0, len(pr))
1754
1755 def test_t2(self):
1756 pr = list(data_schema.validate(
1757 ["a", None, {"key": "value"}],
1758 {"type": "tuple",
1759 "items": [
1760 {"type": "string"},
1761 {"type": None},
1762 {"type": "accept"}]}))
1763 self.assertEqual(0, len(pr))
1764
1765 def test_t3(self):
1766 pr = list(data_schema.validate(
1767 ["a", None, {"key": "value"}],
1768 {"type": "tuple",
1769 "items": [
1770 {"type": "string"},
1771 {"type": None},
1772 {"type": "deny"}]}))
1773 self.assertEqual(1, len(pr))
1774 self.assertEqual(10010, pr[0].code)
1775 self.assertEqual(2, pr[0].context.index)
1776
1777 def test_t4(self):
1778 pr = list(data_schema.validate(
1779 ["a", None, {"key": "value"}],
1780 {"type": "tuple",
1781 "items": [
1782 {"type": "string"},
1783 {"type": None}]}))
1784 self.assertEqual(1, len(pr))
1785 self.assertEqual(10017, pr[0].code)
1786 self.assertEqual(2, pr[0].context.index)
1787
1788 def test_t5(self):
1789 pr = list(data_schema.validate(
1790 ["a", None, {"key": "value"}],
1791 {"type": "tuple",
1792 "items": [
1793 {"type": "string"},
1794 {"type": None}],
1795 "additionalItems": True}))
1796 self.assertEqual(0, len(pr))
1797
1798 def test_t6(self):
1799 pr = list(data_schema.validate(
1800 ["a", None, {"key": "value"}, {"key": "value"}],
1801 {"type": "tuple",
1802 "items": [
1803 {"type": "string"},
1804 {"type": None}],
1805 "additionalItems": {
1806 "type": "dict",
1807 "keys": {"key": {"type": "string"}}
1808 }}))
1809 self.assertEqual(0, len(pr))
1810
1811 def test_t7(self):
1812 # do not check anything that exceeds maxLength
1813 pr = list(data_schema.validate(
1814 ["a", None, {"key": "value"}, {"key": "value"}, {"key2": "value"}],
1815 {"type": "tuple",
1816 "maxLength": 4,
1817 "items": [
1818 {"type": "string"},
1819 {"type": None}],
1820 "additionalItems": {
1821 "type": "dict",
1822 "keys": {"key": {"type": "string"}}
1823 }}))
1824 self.assertEqual(1, len(pr))
1825 self.assertEqual(10016, pr[0].code)
1826
1827 def test_t8(self):
1828 # do not check anything that exceeds maxLength
1829 pr = list(data_schema.validate(
1830 ["a", None, {"key": "value"}, {"key": "value"}, {"key2": "value"}],
1831 {"type": "tuple",
1832 "minLength": 6,
1833 "maxLength": 4,
1834 "items": [
1835 {"type": "string"},
1836 {"type": None}],
1837 "additionalItems": {
1838 "type": "dict",
1839 "keys": {"key": {"type": "string"}}
1840 }}))
1841 self.assertEqual(2, len(pr))
1842 self.assertEqual(10015, pr[0].code)
1843 self.assertEqual(10016, pr[1].code)
1844
1845 def test_set1(self):
1846 # do not check anything that exceeds maxLength
1847 pr = list(data_schema.validate(
1848 set(["a", None, "b"]),
1849 {"type": "set",
1850 "minLength": 3,
1851 "items": {"any-of": [
1852 {"type": "string"},
1853 {"type": None}]}}
1854 ))
1855 self.assertEqual(0, len(pr))
1856
1857 def test_set1_not_nullable(self):
1858 # do not check anything that exceeds maxLength
1859 pr = list(data_schema.validate(
1860 None,
1861 {"type": "set"}))
1862 self.assertEqual(1, len(pr))
1863 self.assertEqual(10038, pr[0].code)
1864
1865 def test_set1_nullable(self):
1866 # do not check anything that exceeds maxLength
1867 pr = list(data_schema.validate(
1868 None,
1869 {"type": "set", "nullable": True}))
1870 self.assertEqual(0, len(pr))
1871
1872 def test_set2(self):
1873 # do not check anything that exceeds maxLength
1874 pr = list(data_schema.validate(
1875 set(["a", None, "b"]),
1876 {"type": "set",
1877 "minLength": 4,
1878 "items": {"any-of": [
1879 {"type": "string"},
1880 {"type": None}]}}
1881 ))
1882 self.assertEqual(1, len(pr))
1883 self.assertEqual(10039, pr[0].code)
1884
1885 def test_set3(self):
1886 # do not check anything that exceeds maxLength
1887 pr = list(data_schema.validate(
1888 set(["a", None, "b"]),
1889 {"type": "set",
1890 "maxLength": 2,
1891 "items": {"any-of": [
1892 {"type": "string"},
1893 {"type": None}]}}
1894 ))
1895 self.assertEqual(1, len(pr))
1896 self.assertEqual(10040, pr[0].code)
1897
1898 def test_set4_itemschema(self):
1899 pr = list(data_schema.validate(
1900 set(["a", None, "b"]),
1901 {"type": "set",
1902 "items": {"any-of": [
1903 {"type": "string"},
1904 {"type": "int"}]}}
1905 ))
1906 codes = set([p.code for p in pr])
1907
1908 self.assertEqual(1, len(pr))
1909 self.assertEqual(10055, pr[0].code)
1910 self.assertEqual(2, len(pr[0].cause))
1911 self.assertEqual(10056, pr[0].cause[0].code)
1912 self.assertEqual(1, len(pr[0].cause[0].cause))
1913 self.assertEqual(10002, pr[0].cause[0].cause[0].code)
1914 self.assertEqual(10056, pr[0].cause[1].code)
1915 self.assertEqual(1, len(pr[0].cause[1].cause))
1916 self.assertEqual(10020, pr[0].cause[1].cause[0].code)
1917
1918 def test_empty(self):
1919 pr = list(data_schema.validate(None, {"type": "empty"}))
1920 self.assertEqual(0, len(pr))
1921
1922 pr = list(data_schema.validate([], {"type": "empty"}))
1923 self.assertEqual(0, len(pr))
1924
1925 pr = list(data_schema.validate(["a"], {"type": "empty"}))
1926 self.assertEqual(1, len(pr))
1927 self.assertEqual(10018, pr[0].code)
1928
1929 pr = list(data_schema.validate(tuple(), {"type": "empty"}))
1930 self.assertEqual(0, len(pr))
1931
1932 pr = list(data_schema.validate(set(), {"type": "empty"}))
1933 self.assertEqual(0, len(pr))
1934
1935 pr = list(data_schema.validate(frozenset(), {"type": "empty"}))
1936 self.assertEqual(0, len(pr))
1937
1938 pr = list(data_schema.validate(tuple(["a"]), {"type": "empty"}))
1939 self.assertEqual(1, len(pr))
1940 self.assertEqual(10018, pr[0].code)
1941
1942 pr = list(data_schema.validate({}, {"type": "empty"}))
1943 self.assertEqual(0, len(pr))
1944
1945 pr = list(data_schema.validate({"key": "value"}, {"type": "empty"}))
1946 self.assertEqual(1, len(pr))
1947 self.assertEqual(10018, pr[0].code)
1948
1949 pr = list(data_schema.validate("", {"type": "empty"}))
1950 self.assertEqual(1, len(pr))
1951 self.assertEqual(10018, pr[0].code)
1952
1953 def test_allOf(self):
1954 pr = list(data_schema.validate(
1955 None,
1956 {"type": {
1957 "all-of": [
1958 {"type": None},
1959 {"type": "accept"},
1960 ]
1961 }}))
1962 self.assertEqual(0, len(pr))
1963
1964 pr = list(data_schema.validate(
1965 None,
1966 {"type": {
1967 "all-of": [
1968 {"type": None},
1969 {"type": "accept"},
1970 {"type": "deny"},
1971 ]
1972 }}))
1973 self.assertEqual(1, len(pr))
1974 self.assertEqual(10057, pr[0].code)
1975 self.assertEqual(1, len(pr[0].cause))
1976 self.assertEqual(10058, pr[0].cause[0].code)
1977 self.assertEqual(1, len(pr[0].cause[0].cause))
1978 self.assertEqual(10010, pr[0].cause[0].cause[0].code)
1979
1980 def test_anyOf(self):
1981 pr = list(data_schema.validate(
1982 None,
1983 {"type": {
1984 "any-of": [
1985 {"type": "deny"},
1986 {"type": None},
1987 ]
1988 }}))
1989 self.assertEqual(0, len(pr))
1990
1991 pr = list(data_schema.validate(
1992 None,
1993 {"type": {
1994 "any-of": [
1995 {"type": "string"},
1996 {"type": "deny"},
1997 ]
1998 }}))
1999 self.assertEqual(1, len(pr))
2000 self.assertEqual(10055, pr[0].code)
2001 self.assertEqual(2, len(pr[0].cause))
2002 self.assertEqual(10056, pr[0].cause[0].code)
2003 self.assertEqual(1, len(pr[0].cause[0].cause))
2004 self.assertEqual(10002, pr[0].cause[0].cause[0].code)
2005 self.assertEqual(10056, pr[0].cause[1].code)
2006 self.assertEqual(1, len(pr[0].cause[1].cause))
2007 self.assertEqual(10010, pr[0].cause[1].cause[0].code)
2008
2009 def test_anyOf_with_list(self):
2010 pr = list(data_schema.validate(
2011 None,
2012 {"type": [
2013 {"type": "deny"},
2014 {"type": None},
2015 ]}))
2016 self.assertEqual(0, len(pr))
2017
2018 pr = list(data_schema.validate(
2019 None,
2020 {"type": [
2021 {"type": "string"},
2022 {"type": "deny"},
2023 ]}))
2024 self.assertEqual(1, len(pr))
2025 self.assertEqual(10055, pr[0].code)
2026 self.assertEqual(2, len(pr[0].cause))
2027 self.assertEqual(10056, pr[0].cause[0].code)
2028 self.assertEqual(1, len(pr[0].cause[0].cause))
2029 self.assertEqual(10002, pr[0].cause[0].cause[0].code)
2030 self.assertEqual(10056, pr[0].cause[1].code)
2031 self.assertEqual(1, len(pr[0].cause[1].cause))
2032 self.assertEqual(10010, pr[0].cause[1].cause[0].code)
2033
2034 def test_oneOf(self):
2035 pr = list(data_schema.validate(
2036 None,
2037 {"type": {
2038 "one-of": [
2039 {"type": "deny"},
2040 {"type": None},
2041 ]
2042 }}))
2043 self.assertEqual(0, len(pr))
2044
2045 pr = list(data_schema.validate(
2046 None,
2047 {"type": {
2048 "one-of": [
2049 {"type": "string"},
2050 {"type": "deny"},
2051 ]
2052 }}))
2053
2054 self.assertEqual(1, len(pr))
2055 self.assertEqual(10053, pr[0].code)
2056 self.assertEqual(2, len(pr[0].cause))
2057 self.assertEqual(10054, pr[0].cause[0].code)
2058 self.assertEqual(1, len(pr[0].cause[0].cause))
2059 self.assertEqual(10002, pr[0].cause[0].cause[0].code)
2060 self.assertEqual(10054, pr[0].cause[1].code)
2061 self.assertEqual(1, len(pr[0].cause[1].cause))
2062 self.assertEqual(10010, pr[0].cause[1].cause[0].code)
2063
2064 pr = list(data_schema.validate(
2065 None,
2066 {"type": {
2067 "one-of": [
2068 {"type": "string"},
2069 {"type": "deny"},
2070 {"type": "empty"},
2071 {"type": None},
2072 ]
2073 }}))
2074 self.assertEqual(1, len(pr))
2075 self.assertEqual(10019, pr[0].code)
2076 self.assertEqual("2,3", pr[0].hint)
2077
2078 def test_not(self):
2079 pr = list(data_schema.validate(
2080 None,
2081 {"type": {
2082 "not": {
2083 "type": "empty"}}}))
2084 self.assertEqual(1, len(pr))
2085 self.assertEqual(10029, pr[0].code)
2086
2087 pr = list(data_schema.validate(
2088 None,
2089 {"type": {
2090 "not": {
2091 "type": {
2092 "not": {
2093 "type": "empty"}}}}}))
2094 self.assertEqual(0, len(pr))
2095
2096 pr = list(data_schema.validate(
2097 2,
2098 {"type": {
2099 "not": {
2100 "type": "int"}}}))
2101 self.assertEqual(1, len(pr))
2102 self.assertEqual(10029, pr[0].code)
2103
2104 pr = list(data_schema.validate(
2105 1,
2106 {"type": {
2107 "not": {
2108 "type": {
2109 "not": {
2110 "type": "int"}}}}}))
2111 self.assertEqual(0, len(pr))
2112
2113 pr = list(data_schema.validate(
2114 2.0,
2115 {"type": {
2116 "not": {
2117 "type": "int"}}}))
2118 self.assertEqual(0, len(pr))
2119
2120 def test_not_shortcut(self):
2121 pr = list(data_schema.validate(
2122 None,
2123 {"not": {
2124 "type": "empty"}}))
2125 self.assertEqual(1, len(pr))
2126 self.assertEqual(10029, pr[0].code)
2127
2128 pr = list(data_schema.validate(
2129 None,
2130 {"not": {
2131 "not": {
2132 "type": "empty"}}}))
2133 self.assertEqual(0, len(pr))
2134
2135 pr = list(data_schema.validate(
2136 2,
2137 {"not": {
2138 "type": "int"}}))
2139 self.assertEqual(1, len(pr))
2140 self.assertEqual(10029, pr[0].code)
2141
2142 pr = list(data_schema.validate(
2143 1,
2144 {"not": {
2145 "not": {
2146 "type": "int"}}}))
2147 self.assertEqual(0, len(pr))
2148
2149 pr = list(data_schema.validate(
2150 2.0,
2151 {"not": {
2152 "type": "int"}}))
2153 self.assertEqual(0, len(pr))
2154
2155 def test_integer(self):
2156 pr = list(data_schema.validate(1, {"type": "integer"}))
2157 self.assertEqual(0, len(pr))
2158
2159 pr = list(data_schema.validate(1, {"type": "float"}))
2160 self.assertEqual(1, len(pr))
2161 self.assertEqual(10023, pr[0].code)
2162
2163 pr = list(data_schema.validate(
2164 2,
2165 {"type": "int",
2166 "minValue": 3,
2167 "maxValue": 1}))
2168
2169 self.assertEqual(2, len(pr))
2170 self.assertEqual(10021, pr[0].code)
2171 self.assertEqual(10022, pr[1].code)
2172
2173 def test_float(self):
2174 pr = list(data_schema.validate(1.8, {"type": "float"}))
2175 self.assertEqual(0, len(pr))
2176
2177 pr = list(data_schema.validate(1, {"type": "float"}))
2178 self.assertEqual(1, len(pr))
2179 self.assertEqual(10023, pr[0].code)
2180
2181 pr = list(data_schema.validate(
2182 2.0,
2183 {"type": "real",
2184 "minValue": 2.1,
2185 "maxValue": 1.9}))
2186
2187 self.assertEqual(2, len(pr))
2188 self.assertEqual(10024, pr[0].code)
2189 self.assertEqual(10025, pr[1].code)
2190
2191 def test_number(self):
2192 pr = list(data_schema.validate(1.8, {"type": "number"}))
2193 self.assertEqual(0, len(pr))
2194 pr = list(data_schema.validate(1, {"type": "num"}))
2195 self.assertEqual(0, len(pr))
2196
2197 pr = list(data_schema.validate(
2198 2.0,
2199 {"type": "number",
2200 "minValue": 3,
2201 "maxValue": 1.3}))
2202
2203 self.assertEqual(2, len(pr))
2204 self.assertEqual(10031, pr[0].code)
2205 self.assertEqual(10032, pr[1].code)
2206
2207 pr = list(data_schema.validate({}, {"type": "number"}))
2208 self.assertEqual(1, len(pr))
2209 self.assertEqual(10030, pr[0].code)
2210
2211 def test_bool(self):
2212 pr = list(data_schema.validate(True, {"type": "bool"}))
2213 self.assertEqual(0, len(pr))
2214
2215 pr = list(data_schema.validate(True, {"type": "boolean",
2216 "value": True}))
2217 self.assertEqual(0, len(pr))
2218
2219 pr = list(data_schema.validate(True, {"type": "boolean",
2220 "value": False}))
2221 self.assertEqual(1, len(pr))
2222 self.assertEqual(10028, pr[0].code)
2223
2224 pr = list(data_schema.validate(False, {"type": "boolean"}))
2225 self.assertEqual(0, len(pr))
2226
2227 pr = list(data_schema.validate(False, {"type": "boolean",
2228 "value": False}))
2229 self.assertEqual(0, len(pr))
2230
2231 pr = list(data_schema.validate(False, {"type": "boolean",
2232 "value": True}))
2233 self.assertEqual(1, len(pr))
2234 self.assertEqual(10027, pr[0].code)
2235
2236 def test_bool_real(self):
2237 pr = list(data_schema.validate([1, 2], {"type": "bool"}))
2238 self.assertEqual(1, len(pr))
2239 self.assertEqual(10026, pr[0].code)
2240
2241 pr = list(data_schema.validate([], {"type": "bool"}))
2242 self.assertEqual(1, len(pr))
2243 self.assertEqual(10026, pr[0].code)
2244
2245 pr = list(data_schema.validate(None, {"type": "bool"}))
2246 self.assertEqual(1, len(pr))
2247 self.assertEqual(10026, pr[0].code)
2248
2249 @staticmethod
2250 def _check_value_ts(obj, schema, context):
2251 if obj == datetime.datetime.fromtimestamp(0):
2252 yield data_schema.ValidationProblem(
2253 code=10042, hint=obj, context=context)
2254
2255 def test_timestamp(self):
2256 pr = list(data_schema.validate(
2257 datetime.datetime.utcnow(),
2258 {"type": "timestamp"}))
2259
2260 pr = list(data_schema.validate(
2261 datetime.datetime.fromtimestamp(180000),
2262 {"type": "datetime",
2263 "value": self._check_value_ts}))
2264 self.assertEqual(0, len(pr))
2265
2266 pr = list(data_schema.validate(
2267 datetime.datetime.fromtimestamp(0),
2268 {"type": "datetime",
2269 "value": self._check_value_ts}))
2270 self.assertEqual(1, len(pr))
2271 self.assertEqual(10042, pr[0].code)
2272
2273 def test_scalar(self):
2274 pr = list(data_schema.validate(1, {"type": "scalar"}))
2275 self.assertEqual(0, len(pr))
2276
2277 pr = list(data_schema.validate("", {"type": "scalar"}))
2278 self.assertEqual(0, len(pr))
2279
2280 pr = list(data_schema.validate(False, {"type": "scalar"}))
2281 self.assertEqual(0, len(pr))
2282
2283 pr = list(data_schema.validate(datetime.datetime.utcnow(),
2284 {"type": "scalar"}))
2285 self.assertEqual(0, len(pr))
2286
2287 pr = list(data_schema.validate(None, {"type": "scalar"}))
2288 self.assertEqual(1, len(pr))
2289 self.assertEqual(10033, pr[0].code)
2290
2291 pr = list(data_schema.validate({}, {"type": "scalar"}))
2292 self.assertEqual(1, len(pr))
2293 self.assertEqual(10033, pr[0].code)
2294
2295 pr = list(data_schema.validate([], {"type": "scalar"}))
2296 self.assertEqual(1, len(pr))
2297 self.assertEqual(10033, pr[0].code)
2298
2299 pr = list(data_schema.validate(tuple(), {"type": "scalar"}))
2300 self.assertEqual(1, len(pr))
2301 self.assertEqual(10033, pr[0].code)
2302
2303 pr = list(data_schema.validate(set(), {"type": "scalar"}))
2304 self.assertEqual(1, len(pr))
2305 self.assertEqual(10033, pr[0].code)
2306
2307 pr = list(data_schema.validate(frozenset(), {"type": "scalar"}))
2308 self.assertEqual(1, len(pr))
2309 self.assertEqual(10033, pr[0].code)
2310
2311 pr = list(data_schema.validate(
2312 None,
2313 {"type": {
2314 "one-of": [
2315 {"type": "scalar"},
2316 {"type": None},
2317 ]}}))
2318 self.assertEqual(0, len(pr))
2319
2320
2321 if __name__ == "__main__":
2322 unittest.main()