annotate data_schema/__init__.py @ 48:a0b464f6ab1f

FIX: Allow only real _Schema instances as schemas in a Context
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 03 Aug 2023 02:19:46 +0200
parents e7f6fc454f84
children 6b8fcd0d2175
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
2 r"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
3 Object schema validation support.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
4
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
5 Somewhat modelled after JSON schema.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
6
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
7 .. seealso:: https://json-schema.org/understanding-json-schema/index.html
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
8
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
9 :Author: Franz Glasner <fzglas.hg@dom66.de>
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
10 :Copyright: \(c) 2023 Franz Glasner
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
11 :License: BSD 3-Clause "New" or "Revised" License.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
12 See :ref:`LICENSE.txt <license>` for details.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
13 :ID: @(#) $Header$
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
14
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
15 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
16
37
ef586378f79a Prepare for development of v0.3: v0.3.dev1
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 34
diff changeset
17 __version__ = "0.3.dev1"
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
18
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
19 __revision__ = "|VCSRevision|"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
20
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
21 __date__ = "|VCSJustDate|"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
22
16
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
23 __all__ = ["SEVERITY", "ERRORS", "WARNINGS",
17
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
24 "problem_message", "problem_severity",
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
25 "ValidationProblem", "SchemaError",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
26 "validate",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
27 "log_problem_cause"]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
28
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
29
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
30 import ast
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
31 import collections
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
32 import copy
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
33 import datetime
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
34 import enum
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
35 import pickle
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
36 import re
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
37 import sys
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
38 import urllib.parse
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
39
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
40 import rfc3986
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
41
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
42 try:
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
43 from configmix.yaml import load as default_schema_loader
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
44 except ImportError:
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
45 default_schema_loader = None
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
46
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
47 from .util import get_data_stream
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
48
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
49
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
50 def NC_(ctx, msg):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
51 """Mimimum dummy translation support"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
52 return msg
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
53
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
54
16
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
55 @enum.unique
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
56 class SEVERITY(enum.IntEnum):
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
57 INFO = 20
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
58 WARNING = 30
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
59 ERROR = 40
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
60
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
61 def __reduce_ex__(self, protocol):
47
e7f6fc454f84 Disable some false positive pylint warnings
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 46
diff changeset
62 return (getattr, (self.__class__, self._name_)) # pylint: disable=no-member
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
63
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
64
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
65 @enum.unique
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
66 class ERRORS(enum.Enum):
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
67 E10000 = NC_("schema-msg", "dict expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
68 E10001 = NC_("schema-msg", "list expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
69 E10002 = NC_("schema-msg", "string expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
70 E10003 = NC_("schema-msg", "dict key must be a string")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
71 E10004 = NC_("schema-msg", "additional key encountered")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
72 E10005 = NC_("schema-msg", "required key(s) missing")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
73 E10006 = NC_("schema-msg", "min string length encountered")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
74 E10007 = NC_("schema-msg", "max string length exceeded")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
75 E10008 = NC_("schema-msg", "string value does not match the required RE pattern")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
76 E10009 = NC_("schema-msg", "string value does not validate")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
77 E10010 = NC_("schema-msg", "validation error")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
78 E10011 = NC_("schema-msg", "None/Null object expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
79 E10012 = NC_("schema-msg", "min list length encountered")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
80 E10013 = NC_("schema-msg", "max list length exceeded")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
81 E10014 = NC_("schema-msg", "tuple expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
82 E10015 = NC_("schema-msg", "min tuple length encountered")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
83 E10016 = NC_("schema-msg", "max tuple length exceeded")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
84 E10017 = NC_("schema-msg", "additional items in tuple not allowed")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
85 E10018 = NC_("schema-msg", "object is not empty")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
86 E10019 = NC_("schema-msg", "more than one match in `one-of' detected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
87 E10020 = NC_("schema-msg", "int expected")
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
88 E10021 = NC_("schema-msg", "int value lower than min-value")
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
89 E10022 = NC_("schema-msg", "int value greater than max-value")
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
90 E10023 = NC_("schema-msg", "float expected")
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
91 E10024 = NC_("schema-msg", "float value lower than min-value")
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
92 E10025 = NC_("schema-msg", "float value greater than max-value")
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
93 E10026 = NC_("schema-msg", "boolean value expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
94 E10027 = NC_("schema-msg", "boolean true expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
95 E10028 = NC_("schema-msg", "boolean false expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
96 E10029 = NC_("schema-msg", "`not' expected problems but got none")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
97 E10030 = NC_("schema-msg", "numeric type (int or float) expected")
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
98 E10031 = NC_("schema-msg", "numeric value lower than min-value")
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
99 E10032 = NC_("schema-msg", "numeric value greater than max-value")
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
100 E10033 = NC_("schema-msg", "a plain scalar value expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
101 E10034 = NC_("schema-msg", "dict key does not match required schema")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
102 E10035 = NC_("schema-msg", "binary data expected")
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
103 E10036 = NC_("schema-msg", "length of binary data lower than min-value")
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
104 E10037 = NC_("schema-msg", "length of binary data exceeds max-value")
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
105 E10038 = NC_("schema-msg", "a set is expected")
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
106 E10039 = NC_("schema-msg", "length of set lower than min-length")
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
107 E10040 = NC_("schema-msg", "length of set greater than max-length")
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
108 E10041 = NC_("schema-msg", "timestamp expected")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
109 E10042 = NC_("schema-msg", "value of timestamp does not validate")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
110 E10043 = NC_("schema-msg", "enumerated string value expected but not found")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
111 E10044 = NC_("schema-msg", "referenced object doest not exist")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
112 E10045 = NC_("schema-msg", "key is not contained in referenced object")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
113 E10046 = NC_("schema-msg", "referenced object is not a container")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
114 E10047 = NC_("schema-msg", "binary data does not match the required RE pattern")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
115 E10048 = NC_("schema-msg", "enumerated integer value expected but not found")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
116 E10049 = NC_("schema-msg", "enumerated number value expected but not found")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
117 E10050 = NC_("schema-msg", "min dict length encountered")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
118 E10051 = NC_("schema-msg", "max dict length exceeded")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
119 E10052 = NC_("schema-msg", "index constraint violated")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
120 E10053 = NC_("schema-msg", "`one-of' failed")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
121 E10054 = NC_("schema-msg", "failing `one-of' item")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
122 E10055 = NC_("schema-msg", "`any-of' failed")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
123 E10056 = NC_("schema-msg", "failing `any-of' item")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
124 E10057 = NC_("schema-msg", "`all-of' failed")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
125 E10058 = NC_("schema-msg", "failing `all-of' item")
38
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
126 E10059 = NC_("schema-msg", "forbidden key detected")
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
127
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
128 def __reduce_ex__(self, protocol):
47
e7f6fc454f84 Disable some false positive pylint warnings
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 46
diff changeset
129 return (getattr, (self.__class__, self._name_)) # pylint: disable=no-member
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
130
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
131
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
132 @enum.unique
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
133 class WARNINGS(enum.Enum):
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
134 W80000 = NC_("schema-msg", "duplicate dict key")
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
135
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
136 def __reduce_ex__(self, protocol):
47
e7f6fc454f84 Disable some false positive pylint warnings
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 46
diff changeset
137 return (getattr, (self.__class__, self._name_)) # pylint: disable=no-member
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
138
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
139
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
140 # Check some invariants at import time
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
141 for e in ERRORS.__members__:
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
142 assert e.startswith('E'), "ERROR code `{}' shall start with letter `E'".format(e)
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
143 assert 10000 <= int(e[1:], 10) < 80000, "Invalid ERROR code number in `{}'".format(e)
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
144 for w in WARNINGS.__members__:
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
145 assert w.startswith('W'), "WARNING code `{}' must start with letter `W'".format(w)
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
146 assert 80000 <= int(w[1:], 10), "Invalid WARNING code number in `{}'".format(w)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
147
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
148
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
149 TYPE_RE = type(re.compile(r"\A.+\Z"))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
150
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
151 SCHEMA_REF_KEY = "$ref"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
152 """Key name for schema references (like a symlink within a schema)"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
153
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
154 SCHEMA_PATH_ROOT = "$root"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
155 """URI path to the root schema"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
156
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
157 SCHEMA_PATH_SELF = "$self"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
158 """URI path to the current schema"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
159
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
160
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
161 class _SENTINELType(object):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
162
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
163 @staticmethod
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
164 def _get_single(module, name):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
165 return getattr(sys.modules[module], name)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
166
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
167 def __reduce_ex__(self, proto):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
168 """Make sure the _SENTINEL is ever only instantiated as singleton"""
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
169 return (_SENTINELType._get_single, (self.__module__, "_SENTINEL"))
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
170
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
171
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
172 _SENTINEL = _SENTINELType()
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
173
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
174
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
175 def problem_message(pr):
17
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
176 """
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
177
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
178 :raises KeyError: the code in `pr` does not refer to
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
179 :class:`.ERRORS` or `.WARNINGS`
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
180
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
181 """
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
182 if isinstance(pr, ValidationProblem):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
183 code = getattr(pr, "code", None)
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
184 elif isinstance(pr, (ERRORS, WARNINGS)):
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
185 code = pr
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
186 else:
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
187 if pr >= 80000:
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
188 code = WARNINGS["W" + str(pr)]
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
189 else:
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
190 code = ERRORS["E" + str(pr)]
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
191 return code.value
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
192
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
193
17
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
194 def problem_severity(pr):
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
195 """Get the default severity for error or warning code `pr`
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
196
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
197 :raises TypeError: if `pr` is not in :class:`.ERRORS` or :class:`.WARNINGS`
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
198
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
199 """
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
200 if pr in ERRORS:
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
201 return SEVERITY.ERROR
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
202 if pr in WARNINGS:
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
203 return SEVERITY.WARNING
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
204 raise TypeError("invalid error or warning code: %r" % (pr, ))
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
205
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
206
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
207 class ValidationProblem(object):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
208
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
209 __slots__ = ("code", "severity", "hint", "context", "cause", "index")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
210
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
211 def __init__(self,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
212 code=None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
213 severity=None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
214 hint=None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
215 context=None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
216 cause=None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
217 index=None):
14
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
218 if code is None:
15
696b83f29363 Use enum props when printing validation problems
Franz Glasner <fzglas.hg@dom66.de>
parents: 14
diff changeset
219 raise TypeError("`code' must be given")
14
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
220 # check validity
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
221 if code not in ERRORS and code not in WARNINGS:
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
222 raise ValueError(
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
223 "unknown validation error code: {}".format(code))
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
224 self.code = code
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
225 if severity is None:
17
65f937fb8de7 Put the computation of the default problem severity into a new public function
Franz Glasner <fzglas.hg@dom66.de>
parents: 16
diff changeset
226 self.severity = problem_severity(code)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
227 else:
16
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
228 if not isinstance(severity, SEVERITY):
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
229 raise TypeError("invalid type for `severity'")
14
cfb97c7c9e5b Simplify ctor of ValidationProblem somewhat
Franz Glasner <fzglas.hg@dom66.de>
parents: 13
diff changeset
230 self.severity = severity
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
231 self.hint = hint
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
232 self.context = context
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
233 if cause:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
234 if not isinstance(cause, (list, tuple, set, frozenset)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
235 cause = (cause, )
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
236 for c in cause:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
237 if not isinstance(c, ValidationProblem):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
238 raise SchemaError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
239 "can only nest other `ValidationProblem' instances")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
240 self.cause = cause
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
241 self.index = index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
242
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
243 def __eq__(self, other):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
244 if not isinstance(other, ValidationProblem):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
245 return NotImplemented
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
246 return ((self.code == other.code)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
247 and (self.severity == other.severity)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
248 and (self.hint == other.hint)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
249 and (self.context == other.context)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
250 and (self.cause == other.cause)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
251 and (self.index == other.index))
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
252
45
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
253 def __ne__(self, other):
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
254 #
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
255 # While the default in Python3 is sensible implementing is recommended
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
256 # when a built-in __eq__ is overwritten (Raymond Hettinger).
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
257 #
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
258 # Do not use not self == other because NotImplemented is not handled
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
259 # properly in some early Python versions (including Py2).
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
260 #
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
261 equal = self.__eq__(other)
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
262 return NotImplemented if equal is NotImplemented else not equal
8a560e0c3180 Implement __ne__ also where __eq__ is implemented
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 44
diff changeset
263
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
264 def __getstate__(self):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
265 return (1, self.code, self.severity, self.hint, self.context,
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
266 self.cause, self.index)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
267
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
268 def __setstate__(self, state):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
269 ver = state[0]
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
270 if ver == 1:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
271 _dummy, self.code, self.severity, self.hint, self.context, self.cause, self.index = state
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
272 else:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
273 raise pickle.UnpicklingError(
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
274 "Unsupported pickle version for ValidationProblem: %d" % (ver,))
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
275
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
276 def __repr__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
277 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
278 msg = " (" + problem_message(self) + ")"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
279 except LookupError:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
280 msg = ""
30
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
281 if self.context is not None:
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
282 context_depth = self.context.depth
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
283 else:
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
284 context_depth = None
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
285 if self.index is None:
16
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
286 return "ValidationProblem(code={}{}, severity={}, hint={}, context=[depth={}]{})".format(
30
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
287 self.code.name, msg, self.severity.name, self.hint, context_depth, self.context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
288 else:
16
2a9e7c4b717e Problem severity now is also an enum
Franz Glasner <fzglas.hg@dom66.de>
parents: 15
diff changeset
289 return "ValidationProblem(code={}{}, severity={}, hint={}, context=[depth={}]{}, index={})".format(
30
2e7c08c356ee Test the the ValidationProblem's str() and repr()
Franz Glasner <fzglas.hg@dom66.de>
parents: 29
diff changeset
290 self.code.name, msg, self.severity.name, self.hint, context_depth, self.context, self.index)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
291
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
292
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
293 class SchemaError(Exception):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
294 """An error within the schema itself"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
295 pass
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
296
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
297
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
298 ValidationSettings = collections.namedtuple(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
299 "ValidationSettings",
29
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
300 ["skip_keys", "break_on_keynames_problems",
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
301 "data_stream_loader", "schema_loader"])
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
302
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
303
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
304 class _Schema(dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
305
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
306 __slots__ = ("parent", "is_sub_root", "_schema_cache")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
307
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
308 def __init__(self, parent, is_sub_root, *args, **kwds):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
309 super().__init__(*args, **kwds)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
310 if parent is None or isinstance(parent, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
311 self.parent = parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
312 else:
25
fd2a40c3d87b Enhance exception message
Franz Glasner <fzglas.hg@dom66.de>
parents: 23
diff changeset
313 raise TypeError(
fd2a40c3d87b Enhance exception message
Franz Glasner <fzglas.hg@dom66.de>
parents: 23
diff changeset
314 "`_Schema' or `None' expected for `parent` argument")
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
315 if parent is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
316 self._schema_cache = {}
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
317 if not is_sub_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
318 raise ValueError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
319 "the root schmema must be a sub-root (aka `$self') also")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
320 self.is_sub_root = True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
321 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
322 self.is_sub_root = is_sub_root
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
323
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
324 def __reduce_ex__(self, proto):
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
325 return super().__reduce_ex__(proto)
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
326
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
327 def __getstate__(self):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
328 return (1, self.parent, self.is_sub_root)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
329
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
330 def __setstate__(self, state):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
331 ver = state[0]
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
332 if ver == 1:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
333 _dummy, self.parent, self.is_sub_root = state
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
334 if self.parent is None:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
335 self._schema_cache = {}
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
336 else:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
337 raise pickle.UnpicklingError(
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
338 "Unsupported pickle version for _Schema: %d" % (ver,))
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
339
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
340 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
341 def ROOT(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
342 """Get the root schema"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
343 r = self
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
344 while r.parent is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
345 r = r.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
346 return r
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
347
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
348 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
349 def SELF(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
350 r = self
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
351 while not r.is_sub_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
352 r = r.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
353 return r
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
354
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
355 def copy(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
356 return _Schema(self.parent, self.is_sub_root, self)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
357
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
358 def get_child(self, name, default=None):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
359 return self.ensure_child_schema(self.get(name, default))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
360
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
361 def ensure_child_schema(self, v):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
362 if v is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
363 return None
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
364 elif isinstance(v, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
365 return v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
366 elif isinstance(v, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
367 return _Schema(self, False, v)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
368 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
369 return v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
370
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
371 def ensure_list_of_child_schemata(self, v):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
372 if isinstance(v, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
373 return [_Schema(self, False, i) for i in v]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
374 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
375 return v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
376
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
377 def __eq__(self, other):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
378 if not isinstance(other, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
379 return NotImplemented
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
380 return (self.parent is other.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
381 and bool(self.is_sub_root) == bool(other.is_sub_root)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
382 and dict(self) == dict(other))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
383
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
384 def __ne__(self, other):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
385 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
386 # While the default in Python3 is sensible implementing is recommended
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
387 # when a built-in __eq__ is overwritten (Raymond Hettinger).
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
388 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
389 # Do not use not self == other because NotImplemented is not handled
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
390 # properly in some early Python versions (including Py2).
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
391 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
392 equal = self.__eq__(other)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
393 return NotImplemented if equal is NotImplemented else not equal
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
394
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
395 def __copy__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
396 return _Schema(self.parent, self.is_sub_root, self)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
397
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
398 def __deepcopy__(self, memo):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
399 return _Schema(self.parent,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
400 self.is_sub_root,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
401 copy.deepcopy(dict(self), memo))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
402
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
403 def __str__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
404 return "<_Schema " + super().__str__() + ">"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
405
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
406 def __repr__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
407 return "<_Schema " + super().__repr__() + ">"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
408
29
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
409 def get_cached_schema(self, key, load_if_needed=True,
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
410 data_stream_loader=None,
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
411 schema_loader=None):
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
412 root = self.ROOT
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
413 s = root._schema_cache.get(key, None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
414 if s is None and load_if_needed:
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
415 if schema_loader is None:
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
416 raise SchemaError("no schema loader available")
29
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
417 dsl = data_stream_loader or get_data_stream
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
418 with dsl(key) as schemastream:
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
419 # load schema a new `$self' (i.e. sub-root is True)
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
420 s = _Schema(self, True, schema_loader(schemastream))
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
421 root._schema_cache[key] = s
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
422 return s
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
423
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
424 def add_cached_schema(self, key, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
425 r = self.ROOT
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
426 assert isinstance(schema, _Schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
427 r._schema_cache[key] = schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
428
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
429
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
430 class Context(object):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
431
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
432 __slots__ = ("_parent", "_key", "_key_index",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
433 "_index",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
434 "root_object", "root_schema",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
435 "_current_object",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
436 "_settings")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
437
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
438 def __init__(self, parent, *, key=_SENTINEL, index=_SENTINEL,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
439 root_object=_SENTINEL, root_schema=_SENTINEL,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
440 current_object=_SENTINEL,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
441 settings=_SENTINEL,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
442 key_index=_SENTINEL):
48
a0b464f6ab1f FIX: Allow only real _Schema instances as schemas in a Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 47
diff changeset
443 if root_schema is not _SENTINEL:
a0b464f6ab1f FIX: Allow only real _Schema instances as schemas in a Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 47
diff changeset
444 if not isinstance(root_schema, _Schema):
a0b464f6ab1f FIX: Allow only real _Schema instances as schemas in a Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 47
diff changeset
445 raise TypeError("schema must be a `_Schema' not a pure `dict'")
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
446 if parent is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
447 if key is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
448 raise TypeError("the root context may not have a key")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
449 if index is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
450 raise TypeError("the root context may not have an index")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
451 if settings is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
452 raise TypeError("the root context must have settings")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
453 self.root_object = root_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
454 if current_object is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
455 current_object = root_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
456 self.root_schema = root_schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
457 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
458 if key is _SENTINEL and index is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
459 raise TypeError("one of `key` and `index` must be given in a non-root context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
460 if root_object is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
461 raise TypeError("non-root context may not have a root object")
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
462 self.root_object = root_object
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
463 if root_schema is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
464 raise TypeError("non-root context may not have a root schema")
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
465 self.root_schema = root_schema
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
466 if key is not _SENTINEL and index is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
467 raise ValueError("only one of `key` and `index` may be given in a context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
468 if key_index is not _SENTINEL and key is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
469 raise ValueError("when having a `key_index` a `key` also must be given")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
470 self._parent = parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
471 self._key = key
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
472 self._key_index = key_index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
473 self._index = index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
474 self._current_object = current_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
475 self._settings = settings
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
476
44
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
477 def __getstate__(self):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
478 return (1, self._parent, self._key, self._key_index, self._index,
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
479 self.root_object, self.root_schema,
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
480 self._current_object, self._settings)
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
481
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
482 def __setstate__(self, state):
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
483 ver = state[0]
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
484 if ver == 1:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
485 _dummy, self._parent, self._key, self._key_index, self._index, self.root_object, self.root_schema, self._current_object, self._settings = state
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
486 else:
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
487 raise pickle.UnpicklingError(
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
488 "Unsupported pickle version for _Context: %d" % (ver,))
ea8c2d01a9d9 Begin pickling support for ValidatenProblems, _Schema and Context
Franz Glasner <fzglas.hg@dom66.de>
parents: 40
diff changeset
489
46
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
490 def __eq__(self, other):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
491 if not isinstance(other, Context):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
492 return NotImplemented
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
493 return ((self._parent == other._parent)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
494 and (self._key == other._key)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
495 and (self._key_index == other._key_index)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
496 # XXX FIXME ???
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
497 # and (self.root_object == other.root_object)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
498 # and (self.root_schema == other.root_schema)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
499 # and (self._current_object == other._current_object)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
500 and (self._settings == other._settings)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
501 )
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
502
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
503 def __ne__(self, other):
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
504 #
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
505 # While the default in Python3 is sensible implementing is recommended
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
506 # when a built-in __eq__ is overwritten (Raymond Hettinger).
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
507 #
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
508 # Do not use not self == other because NotImplemented is not handled
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
509 # properly in some early Python versions (including Py2).
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
510 #
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
511 equal = self.__eq__(other)
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
512 return NotImplemented if equal is NotImplemented else not equal
92ae1e882cef Enhance pickling support
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 45
diff changeset
513
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
514 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
515 def parent(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
516 return self._parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
517
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
518 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
519 def safe_parent(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
520 if self.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
521 raise TypeError("the root context has no parent")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
522 return self.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
523
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
524 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
525 def root(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
526 """Get the root context"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
527 ctx = self
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
528 while not ctx.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
529 ctx = ctx.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
530 return ctx
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
531
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
532 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
533 def is_root(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
534 return not bool(self.parent)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
535
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
536 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
537 def key(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
538 if self._key is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
539 raise AttributeError("no `key' in Context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
540 return self._key
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
541
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
542 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
543 def index(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
544 if self._index is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
545 raise AttributeError("no `index' in Context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
546 return self._index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
547
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
548 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
549 def key_index(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
550 if self._key_index is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
551 raise AttributeError("no `key_index' in Context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
552 return self._key_index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
553
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
554 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
555 def current_object(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
556 if self._current_object is _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
557 raise AttributeError("no `current_object' in Context")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
558 return self._current_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
559
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
560 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
561 def settings(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
562 s = self._settings
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
563 return s if s is not _SENTINEL else self.parent.settings
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
564
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
565 @property
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
566 def depth(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
567 if self._key is _SENTINEL and self._index is _SENTINEL and self.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
568 return 0
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
569 n = 0
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
570 ctx = self
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
571 while not ctx.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
572 n += 1
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
573 ctx = ctx.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
574 return n
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
575
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
576 def __str__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
577 if self._key is _SENTINEL and self._index is _SENTINEL and self.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
578 return "<ROOT>"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
579 chain = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
580 ctx = self
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
581 while not ctx.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
582 if ctx._key is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
583 chain.append(str(ctx.key))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
584 elif ctx._index is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
585 chain.append("INDEX:{}".format(ctx.index))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
586 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
587 chain.append("")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
588 ctx = ctx.parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
589 chain.reverse()
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
590 return " / ".join(chain)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
591
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
592 def __repr__(self):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
593 return "<Context path=`{}'>".format(str(self))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
594
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
595
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
596 def _get_one_of(d, *keys, default=None, strict=True):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
597 """Get the first found key and its value of `keys` from dict `d`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
598
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
599 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
600 for k in keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
601 v = d.get(k, _SENTINEL)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
602 if v is not _SENTINEL:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
603 if strict:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
604 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
605 # check that all no other key of `keys` besides of `k` is
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
606 # in `d`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
607 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
608 other_keys = set(keys)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
609 other_keys.remove(k)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
610 for k2 in other_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
611 if k2 in d:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
612 raise SchemaError("ambiguous key from: {}".format(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
613 ", ".join(keys)))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
614 return k, v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
615 return None, default
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
616
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
617
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
618 def validate(obj, schema, **kwds):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
619 """Validate object `obj` against the *specific* schema `schema`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
620
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
621 Yields errors and warnings
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
622
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
623 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
624 settings = {
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
625 "skip_keys": None,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
626 "break_on_keynames_problems": True,
29
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
627 "data_stream_loader": get_data_stream,
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
628 "schema_loader": default_schema_loader
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
629 }
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
630 settings.update(kwds)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
631 if not isinstance(schema, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
632 if not isinstance(schema, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
633 raise SchemaError("Schema must be a dict-alike."
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
634 " Got: {!r}".format(schema))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
635 schema = _Schema(None, True, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
636 context = Context(None, root_object=obj, root_schema=schema,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
637 settings=ValidationSettings(**settings))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
638 yield from _validate(obj, schema, context, is_root=True)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
639
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
640
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
641 def _validate(obj, schema, context, is_root=False):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
642 """Validate object `obj` against the *specific* schema `schema`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
643
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
644 Yields errors and warnings
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
645
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
646 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
647 if not isinstance(schema, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
648 raise SchemaError("Schema must be a `_Schema'."
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
649 " Got: {!r}. Context: {!s}".format(schema, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
650 # 1. Process "cond" or "match"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
651 schema = process_schema_conditionals(schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
652 # 2. Process "$ref" schema references
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
653 schema = process_schema_references(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
654 schema, context, check_single_ref_key=not is_root)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
655
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
656 # 3. Real validation
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
657
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
658 # check combinator shortcuts without "$type" indirection
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
659 combinator, combinator_schema = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
660 schema, "not", "all-of", "any-of", "one-of")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
661 if combinator is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
662 try:
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
663 t = schema["$type"]
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
664 except KeyError:
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
665 raise SchemaError("Schema has no `$type' key: {!r}."
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
666 " Context: {!s}".format(schema, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
667 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
668 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
669 # Construct a temporary schema with the proper indirection for
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
670 # the check below
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
671 #
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
672 t = {"$type": {combinator: combinator_schema}}
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
673 if combinator_schema is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
674 raise SchemaError("a combinator requires a child")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
675 if callable(t):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
676 yield from t(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
677 elif t is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
678 yield from validate_null(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
679 elif isinstance(t, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
680 if len(t) != 1:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
681 raise SchemaError("type dict must be of length 1")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
682 # Check whether a shortcut is already seen above
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
683 if combinator is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
684 combinator = list(t.keys())[0]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
685 combinator_schema = t[combinator]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
686 if combinator == "not":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
687 yield from validate_not(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
688 obj, schema.ensure_child_schema(combinator_schema), context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
689 elif combinator == "all-of":
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
690 yield from validate_all_of(
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
691 obj,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
692 schema.ensure_list_of_child_schemata(combinator_schema),
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
693 context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
694 elif combinator == "any-of":
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
695 yield from validate_any_of(
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
696 obj,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
697 schema.ensure_list_of_child_schemata(combinator_schema),
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
698 context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
699 elif combinator == "one-of":
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
700 yield from validate_one_of(
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
701 obj,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
702 schema.ensure_list_of_child_schemata(combinator_schema),
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
703 context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
704 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
705 raise SchemaError("unknown combinator: {}".format(combinator))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
706 elif isinstance(t, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
707 # a simple list is "any-of"
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
708 yield from validate_any_of(
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
709 obj, schema.ensure_list_of_child_schemata(t), context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
710 elif t in ("dict", "map", "object"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
711 yield from validate_dict(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
712 elif t in ("list", "array",):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
713 yield from validate_list(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
714 elif t in ("tuple", "record"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
715 yield from validate_tuple(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
716 elif t in ("set", "frozenset"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
717 yield from validate_set(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
718 elif t in ("string", "str"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
719 yield from validate_str(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
720 elif t in ("deny", ):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
721 yield from validate_deny(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
722 elif t in ("accept", ):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
723 yield from validate_accept(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
724 elif t in ("none", "null", "nil"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
725 yield from validate_null(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
726 elif t in ("empty", ):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
727 yield from validate_empty(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
728 elif t in ("integer", "int"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
729 yield from validate_integer(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
730 elif t in ("float", "real", "double"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
731 yield from validate_float(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
732 elif t in ("number", "num"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
733 yield from validate_number(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
734 elif t in ("bool", "boolean"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
735 yield from validate_bool(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
736 elif t in ("scalar", ):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
737 yield from validate_scalar(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
738 elif t in ("binary", ):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
739 yield from validate_binary(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
740 elif t in ("timestamp", "datetime"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
741 yield from validate_timestamp(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
742 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
743 raise SchemaError("unknown type in schema: {}".format(t))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
744
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
745
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
746 def _is_in_skip_keys(key, skip_keys):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
747 if not skip_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
748 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
749 for sk in skip_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
750 if isinstance(sk, str):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
751 if key == sk:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
752 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
753 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
754 if sk.search(key):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
755 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
756 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
757
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
758
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
759 def _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
760 if obj is None and schema.get("nullable", False):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
761 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
762 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
763
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
764
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
765 def _validate_index_constraint(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
766 # No evaluation of index constraints for the root context
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
767 if context.is_root:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
768 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
769 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
770 index_constraints = schema["index-constraint"]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
771 except KeyError:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
772 return # no constraints
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
773 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
774 if not isinstance(index_constraints, (list, tuple, set, frozenset)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
775 index_constraints = [index_constraints]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
776 if not index_constraints:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
777 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
778 parent = context.safe_parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
779 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
780 effective_index = context.index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
781 except AttributeError:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
782 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
783 effective_index = context.key_index
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
784 except AttributeError:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
785 raise SchemaError("parent container has no usable index")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
786 for idx in index_constraints:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
787 if idx < 0:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
788 idx = len(parent.current_object) + idx
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
789 if idx == effective_index:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
790 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
791 else:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
792 yield ValidationProblem(code=ERRORS.E10052, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
793
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
794
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
795 def validate_dict(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
796 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
797 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
798 if not isinstance(obj, dict):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
799 yield ValidationProblem(code=ERRORS.E10000, hint="got: {}".format(type(obj).__name__), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
800 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
801 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
802 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
803 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
804 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
805 yield ValidationProblem(code=ERRORS.E10050, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
806 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
807 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
808 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
809 yield ValidationProblem(code=ERRORS.E10051, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
810 schema_keys = schema.get("keys", {}) if schema else {}
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
811 seen_keys = set()
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
812 schema_keynames = schema.get_child("key-names", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
813 idx = -1
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
814 for key, item in obj.items():
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
815 idx += 1
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
816 if schema_keynames is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
817 if not isinstance(key, str):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
818 yield ValidationProblem(code=ERRORS.E10003, hint=repr(key), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
819 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
820 # validate the key against given schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
821 new_context = Context(context, key=key, key_index=idx, current_object=key)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
822 key_probs = list(_validate(key, schema_keynames, new_context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
823 if key_probs:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
824 yield ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
825 code=ERRORS.E10034, hint=key, context=context, cause=key_probs)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
826 if context.settings.break_on_keynames_problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
827 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
828 if key in seen_keys:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
829 yield ValidationProblem(code=WARNINGS.W80000, hint=key, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
830 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
831 seen_keys.add(key)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
832 # XXX FIXME: context: new leaf context with new key for recursion
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
833 if key in schema_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
834 new_context = Context(context, key=key, key_index=idx, current_object=item)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
835 yield from _validate(item, schema.ensure_child_schema(schema_keys[key]), new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
836 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
837 # check whether additional keys are allowed
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
838 additional_keys = schema.get_child("additional-keys", False)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
839 if isinstance(additional_keys, bool):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
840 if not additional_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
841 if not _is_in_skip_keys(key, context.settings.skip_keys):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
842 yield ValidationProblem(code=ERRORS.E10004, hint=str(key), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
843 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
844 if not _is_in_skip_keys(key, context.settings.skip_keys):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
845 # try this as the common schema for all the additional keys
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
846 new_context = Context(context, key=key, key_index=idx, current_object=item)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
847 yield from _validate(item, additional_keys, new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
848 # check whether all required keys are seen
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
849 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
850 required_keys = set(schema.get("required", set()))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
851 except (TypeError, ValueError):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
852 raise SchemaError("`required` must be an iterable")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
853 if not required_keys <= seen_keys:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
854 hs = [str(i) for i in required_keys - seen_keys]
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
855 yield ValidationProblem(code=ERRORS.E10005, hint=sorted(hs), context=context)
38
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
856 # check whether no forbidden keys are seen
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
857 try:
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
858 forbidden_keys = set(schema.get("forbidden", set()))
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
859 except (TypeError, ValueError):
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
860 raise SchemaError("`forbidden` must be an iterable")
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
861 if forbidden_keys & seen_keys:
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
862 hs = [str(i) for i in forbidden_keys & seen_keys]
5a2fba996773 Implement a "forbidden" schema field for dicts
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 37
diff changeset
863 yield ValidationProblem(code=ERRORS.E10059, hint=sorted(hs), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
864
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
865
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
866 def validate_list(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
867 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
868 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
869 if not isinstance(obj, (list, tuple)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
870 yield ValidationProblem(code=ERRORS.E10001, hint="got: {}".format(type(obj).__name__), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
871 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
872 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
873 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
874 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
875 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
876 yield ValidationProblem(code=ERRORS.E10012, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
877 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
878 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
879 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
880 yield ValidationProblem(code=ERRORS.E10013, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
881 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
882 schema_items = schema.ensure_child_schema(schema["items"])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
883 except KeyError:
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
884 schema_items = _Schema(schema, False, {"$type": validate_deny})
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
885 for idx, o in enumerate(obj):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
886 new_context = Context(parent=context, index=idx, current_object=o)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
887 yield from _validate(o, schema_items, new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
888
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
889
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
890 def validate_set(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
891 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
892 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
893 if not isinstance(obj, (set, frozenset)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
894 yield ValidationProblem(code=ERRORS.E10038, hint="got: {}".format(type(obj).__name__), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
895 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
896 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
897 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
898 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
899 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
900 yield ValidationProblem(code=ERRORS.E10039, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
901 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
902 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
903 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
904 yield ValidationProblem(code=ERRORS.E10040, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
905 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
906 schema_items = schema.ensure_child_schema(schema["items"])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
907 except KeyError:
31
271ec3abdfa3 Use "$type" as the schema's type specifier instead of "type".
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 30
diff changeset
908 schema_items = _Schema(schema, False, {"$type": validate_deny})
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
909 for o in obj:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
910 new_context = Context(parent=context, key=o, current_object=o)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
911 yield from _validate(o, schema_items, new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
912
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
913
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
914 def validate_tuple(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
915 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
916 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
917 if not isinstance(obj, (list, tuple)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
918 yield ValidationProblem(code=ERRORS.E10014, hint="got: {}".format(type(obj).__name__), context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
919 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
920 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
921 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
922 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
923 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
924 yield ValidationProblem(code=ERRORS.E10015, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
925 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
926 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
927 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
928 yield ValidationProblem(code=ERRORS.E10016, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
929 schema_items = schema.get("items", [])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
930 if not isinstance(schema_items, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
931 raise SchemaError("tuple items require a list of schemata in items")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
932 for idx, o in enumerate(obj):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
933 # early exit at maxlen
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
934 if maxlen is not None and idx >= maxlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
935 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
936 new_context = Context(parent=context, index=idx, current_object=o)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
937 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
938 schema_index = schema.ensure_child_schema(schema_items[idx])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
939 except IndexError:
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
940 additional_items = schema.get_child("additional-items", False)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
941 if isinstance(additional_items, bool):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
942 if not additional_items:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
943 yield ValidationProblem(code=ERRORS.E10017, context=new_context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
944 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
945 yield from _validate(o, additional_items, new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
946 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
947 yield from _validate(o, schema_index, new_context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
948
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
949
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
950 def validate_str(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
951 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
952 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
953 if not isinstance(obj, str):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
954 yield ValidationProblem(code=ERRORS.E10002, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
955 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
956 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
957 enumvalues = schema.get("enum", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
958 if enumvalues is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
959 for ev in enumvalues:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
960 if ev == obj:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
961 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
962 else:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
963 yield ValidationProblem(code=ERRORS.E10043, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
964 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
965 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
966 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
967 yield ValidationProblem(code=ERRORS.E10006, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
968 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
969 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
970 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
971 yield ValidationProblem(code=ERRORS.E10007, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
972 pattern = schema.get("pattern", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
973 if pattern is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
974 if isinstance(pattern, str):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
975 mo = re.search(pattern, obj)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
976 if not mo:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
977 yield ValidationProblem(code=ERRORS.E10008, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
978 elif isinstance(pattern, TYPE_RE):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
979 mo = pattern.search(obj)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
980 if not mo:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
981 yield ValidationProblem(code=ERRORS.E10008, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
982 elif callable(pattern):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
983 yield from pattern(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
984 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
985 raise SchemaError("unknown pattern type")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
986 is_contained = schema.get("is-contained-in-ref", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
987 if is_contained is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
988 refobj = try_get_reference(is_contained,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
989 context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
990 schema,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
991 default=_SENTINEL)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
992 if refobj is _SENTINEL:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
993 yield ValidationProblem(code=ERRORS.E10044, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
994 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
995 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
996 if obj not in refobj:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
997 yield ValidationProblem(code=ERRORS.E10045, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
998 except TypeError:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
999 yield ValidationProblem(code=ERRORS.E10046, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1000
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1001
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1002 def validate_binary(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1003 if not isinstance(obj, (bytes, bytearray)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1004 yield ValidationProblem(code=ERRORS.E10035, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1005 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1006 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1007 minlen = schema.get("min-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1008 if minlen:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1009 if len(obj) < minlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1010 yield ValidationProblem(code=ERRORS.E10036, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1011 maxlen = schema.get("max-length", None)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1012 if maxlen is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1013 if len(obj) > maxlen:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1014 yield ValidationProblem(code=ERRORS.E10037, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1015 pattern = schema.get("pattern", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1016 if pattern is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1017 if isinstance(pattern, (str, bytes, bytearray)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1018 if isinstance(pattern, str):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1019 if "'''" not in pattern:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1020 bytes_pattern = ast.literal_eval(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1021 "b'''" + pattern + "'''")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1022 elif '"""' not in pattern:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1023 bytes_pattern = ast.literal_eval(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1024 'b"""' + pattern + '"""')
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1025 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1026 raise SchemaError("incompatible bytes pattern")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1027 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1028 bytes_pattern = pattern
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1029 mo = re.search(bytes_pattern, obj)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1030 if not mo:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1031 yield ValidationProblem(code=ERRORS.E10047, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1032 elif isinstance(pattern, TYPE_RE):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1033 mo = pattern.search(obj)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1034 if not mo:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1035 yield ValidationProblem(code=ERRORS.E10047, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1036 elif callable(pattern):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1037 yield from pattern(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1038 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1039 raise SchemaError("unknown pattern type")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1040
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1041
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1042 def validate_timestamp(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1043 if not isinstance(obj, datetime.datetime):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1044 yield ValidationProblem(code=ERRORS.E10041, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1045 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1046 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1047 value = schema.get("value", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1048 if value is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1049 if callable(value):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1050 yield from value(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1051 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1052 raise SchemaError("unknown value validator (only a callable allowed)")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1053
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1054
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1055 def validate_integer(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1056 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1057 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1058 if not isinstance(obj, int):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1059 yield ValidationProblem(code=ERRORS.E10020, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1060 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1061 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1062 min_value = schema.get("min-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1063 if min_value is not None and obj < min_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1064 yield ValidationProblem(code=ERRORS.E10021, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1065 max_value = schema.get("max-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1066 if max_value is not None and obj > max_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1067 yield ValidationProblem(code=ERRORS.E10022, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1068 enumvalues = schema.get("enum", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1069 if enumvalues is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1070 for ev in enumvalues:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1071 if ev == obj:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1072 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1073 else:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1074 yield ValidationProblem(code=ERRORS.E10048, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1075 value = schema.get("value", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1076 if value is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1077 if callable(value):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1078 yield from value(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1079 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1080 raise SchemaError("unknown value validator (only a callable allowed)")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1081
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1082
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1083 def validate_float(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1084 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1085 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1086 if not isinstance(obj, float):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1087 yield ValidationProblem(code=ERRORS.E10023, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1088 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1089 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1090 min_value = schema.get("min-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1091 if min_value is not None and obj < min_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1092 yield ValidationProblem(code=ERRORS.E10024, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1093 max_value = schema.get("max-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1094 if max_value is not None and obj > max_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1095 yield ValidationProblem(code=ERRORS.E10025, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1096 value = schema.get("value", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1097 if value is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1098 if callable(value):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1099 yield from value(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1100 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1101 raise SchemaError("unknown value validator (only a callable allowed)")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1102
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1103
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1104 def validate_number(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1105 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1106 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1107 if not isinstance(obj, (int, float)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1108 yield ValidationProblem(code=ERRORS.E10030, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1109 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1110 yield from _validate_index_constraint(obj, schema, context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1111 min_value = schema.get("min-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1112 if min_value is not None and isinstance(obj, float):
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1113 min_value *= 1.0
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1114 if min_value is not None and obj < min_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1115 yield ValidationProblem(code=ERRORS.E10031, hint=obj, context=context)
19
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1116 max_value = schema.get("max-value", None)
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1117 if max_value is not None and isinstance(obj, float):
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1118 max_value *= 1.0
c3a0fe8d4587 Consistent casing of schema items: all lowercase with dash as separator
Franz Glasner <fzglas.hg@dom66.de>
parents: 17
diff changeset
1119 if max_value is not None and obj > max_value:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1120 yield ValidationProblem(code=ERRORS.E10032, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1121 enumvalues = schema.get("enum", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1122 if enumvalues is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1123 for ev in enumvalues:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1124 if ev == obj:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1125 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1126 else:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1127 yield ValidationProblem(code=ERRORS.E10049, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1128 value = schema.get("value", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1129 if value is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1130 if callable(value):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1131 yield from value(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1132 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1133 raise SchemaError("unknown value validator (only a callable allowed)")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1134
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1135
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1136 def validate_scalar(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1137 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1138 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1139 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1140 if obj is None:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1141 yield ValidationProblem(code=ERRORS.E10033, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1142 if isinstance(obj, (dict, list, tuple, set, frozenset)):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1143 yield ValidationProblem(code=ERRORS.E10033, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1144
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1145
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1146 def validate_deny(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1147 yield from _validate_index_constraint(obj, schema, context)
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1148 yield ValidationProblem(code=ERRORS.E10010, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1149
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1150
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1151 def validate_accept(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1152 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1153
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1154
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1155 def validate_null(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1156 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1157 if obj is not None:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1158 yield ValidationProblem(code=ERRORS.E10011, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1159
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1160
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1161 def validate_empty(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1162 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1163 if obj is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1164 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1165 if isinstance(obj, (dict, list, tuple, set, frozenset)) and not obj:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1166 return
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1167 yield ValidationProblem(ERRORS.E10018, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1168
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1169
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1170 def validate_bool(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1171 if _is_null_allowed_for_object(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1172 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1173 if not isinstance(obj, bool):
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1174 yield ValidationProblem(code=ERRORS.E10026, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1175 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1176 yield from _validate_index_constraint(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1177 value = schema.get("value", None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1178 if value is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1179 if callable(value):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1180 yield from value(obj, schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1181 elif value and not obj:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1182 yield ValidationProblem(code=ERRORS.E10027, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1183 elif not value and obj:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1184 yield ValidationProblem(code=ERRORS.E10028, hint=obj, context=context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1185
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1186
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
1187 def validate_all_of(obj, schema, context):
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1188 if not isinstance(schema, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1189 raise SchemaError("require a list of schematas for `all-of'")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1190 res = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1191 for idx, s in enumerate(schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1192 assert isinstance(s, _Schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1193 tr = list(_validate(obj, s, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1194 if tr:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1195 res.append((idx, tr, ))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1196 if res:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1197 yield ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1198 code=ERRORS.E10057,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1199 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1200 cause=[
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1201 ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1202 code=ERRORS.E10058,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1203 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1204 cause=tr,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1205 index=idx) for (idx, tr) in res])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1206
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1207
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
1208 def validate_any_of(obj, schema, context):
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1209 if not isinstance(schema, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1210 raise SchemaError("require a list of schematas for `any-of'")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1211 res = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1212 for s in schema:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1213 assert isinstance(s, _Schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1214 tr = list(_validate(obj, s, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1215 if tr:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1216 res.append(tr)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1217 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1218 # Erfolg: gleich positiv zurueck ohne Meldungen
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1219 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1220 # Ansonsten: alle Fehlschlaege protokollieren
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1221 if res:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1222 yield ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1223 code=ERRORS.E10055,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1224 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1225 cause=[
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1226 ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1227 code=ERRORS.E10056,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1228 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1229 cause=tr) for tr in res])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1230
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1231
23
413b344be2d1 Consistent naming of validation methods: all lowercase
Franz Glasner <fzglas.hg@dom66.de>
parents: 19
diff changeset
1232 def validate_one_of(obj, schema, context):
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1233 if not isinstance(schema, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1234 raise SchemaError("require a list of schematas for `one-of'")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1235 success_res = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1236 failed_res = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1237 for idx, s in enumerate(schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1238 assert isinstance(s, _Schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1239 tr = list(_validate(obj, s, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1240 if tr:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1241 failed_res.append((idx, tr, ))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1242 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1243 success_res.append(idx)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1244 if len(success_res) == 1:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1245 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1246 elif len(success_res) == 0:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1247 # Ansonsten: alle Fehlschlaege protokollieren
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1248 if failed_res:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1249 yield ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1250 code=ERRORS.E10053,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1251 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1252 cause=[
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1253 ValidationProblem(
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1254 code=ERRORS.E10054,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1255 context=context,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1256 cause=tr,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1257 index=idx) for (idx, tr) in failed_res])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1258 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1259 # Die Indizes der "zuvielen" in "hint" anzeigen
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1260 yield ValidationProblem(code=ERRORS.E10019, hint=",".join([str(k) for k in success_res]))
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1261
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1262
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1263 def validate_not(obj, schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1264 assert isinstance(schema, _Schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1265 res = list(_validate(obj, schema, context))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1266 if not res:
13
940676a0de84 ERRORS and WARNINGS are now enums
Franz Glasner <fzglas.hg@dom66.de>
parents: 10
diff changeset
1267 yield ValidationProblem(code=ERRORS.E10029, hint=obj, context=context,
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1268 cause=res)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1269
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1270
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1271 def process_schema_references(schema, context, check_single_ref_key=True):
40
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1272 """
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1273
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1274 .. note:: If a new dereferenced schema is found schema conditionals are
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1275 evaluated also. So the resolved schema containing conditionals
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1276 behaves according to the given conditions.
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1277
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1278 """
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1279 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1280 ref = schema[SCHEMA_REF_KEY]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1281 except (KeyError, TypeError):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1282 return schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1283 # if `$ref' is found it MUST be the only key
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1284 if check_single_ref_key and len(schema) != 1:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1285 raise SchemaError("`{}' must be the single key if it exists")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1286 schema = try_get_reference(ref, context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1287 if not isinstance(schema, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1288 raise SchemaError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1289 "dereferenced schema is not a `_Schema': {}".format(ref))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1290 schema = copy.deepcopy(schema)
40
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1291 # process schema conditionals "cond" and "match" again
2376224a9717 FIX: when processing schema references and the resolved schema contains conditionals they must be evaluated
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 39
diff changeset
1292 schema = process_schema_conditionals(schema, context)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1293 return process_schema_references(schema, context, check_single_ref_key=True)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1294
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1295
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1296 def process_schema_conditionals(schema, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1297 """Lisp-like `cond` to provide schema modifications
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1298
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1299 :param schema: the input schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1300 :param context: the validation context with a valid
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1301 `context.root.root_object`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1302 :returns: the processed schema: the schema itself if it is unchanged and
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1303 a copy of the schema if has been changed
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1304
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1305 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1306 what, conds = _get_one_of(schema, "cond", "match", default=None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1307 if what is None or conds is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1308 return schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1309 if not isinstance(conds, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1310 raise SchemaError("the conditions of a cond must be a sequence")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1311 if what == "cond":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1312 return _process_schema_conditionals_cond(schema, conds, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1313 elif what == "match":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1314 return _process_schema_conditionals_match(schema, conds, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1315 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1316 assert False, "unreachable"
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1317
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1318
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1319 def _process_schema_conditionals_cond(schema, conds, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1320 for cond in conds:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1321 if not isinstance(cond, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1322 raise SchemaError("a single condition must be a dict")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1323 if eval_condition(cond, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1324 rep_type, rep_schema = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1325 cond, "then", "then-replace", "then-merge")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1326 rep_schema = schema.ensure_child_schema(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1327 if rep_type in ("then", "then-replace"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1328 do_merge = False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1329 elif rep_type == "then-merge":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1330 do_merge = True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1331 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1332 raise SchemaError("unknown then type: {}".format(rep_type))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1333 break
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1334 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1335 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1336 # No condition was true: just remove the "cond" to get the
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1337 # effective schema.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1338 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1339 rep_schema = None
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1340 do_merge = False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1341
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1342 new_schema = schema.copy()
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1343 del new_schema["cond"]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1344 if rep_schema:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1345 rep_schema = process_schema_references(rep_schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1346 # this could insert a new nested "cond" or "match" again
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1347 if do_merge:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1348 rep_schema = copy.deepcopy(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1349 new_schema = _merge(rep_schema, new_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1350 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1351 new_schema.update(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1352 # Recursively apply "cond/match" evaluation to the resulting schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1353 return process_schema_conditionals(new_schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1354
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1355
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1356 def _process_schema_conditionals_match(schema, conds, context):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1357 rep_schemata = []
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1358 for cond in conds:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1359 if not isinstance(cond, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1360 raise SchemaError("a single condition must be a dict")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1361 if eval_condition(cond, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1362 rep_type, rep_schema = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1363 cond, "then", "then-replace", "then-merge")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1364 rep_schema = schema.ensure_child_schema(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1365 if rep_type in ("then", "then-replace"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1366 rep_schemata.append((False, rep_schema))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1367 elif rep_type == "then-merge":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1368 rep_schemata.append((True, rep_schema))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1369 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1370 raise SchemaError("unknown then type: {}".format(rep_type))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1371
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1372 new_schema = schema.copy()
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1373 del new_schema["match"]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1374 for do_merge, rep_schema in rep_schemata:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1375 rep_schema = process_schema_references(rep_schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1376 # this could insert a new nested "cond" or "match" again
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1377 if do_merge:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1378 rep_schema = copy.deepcopy(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1379 new_schema = _merge(rep_schema, new_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1380 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1381 new_schema.update(rep_schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1382 # Recursively apply "cond/match" evaluation to the resulting schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1383 return process_schema_conditionals(new_schema, context)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1384
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1385
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1386 def eval_condition(cond, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1387 """Eval the condition in `cond` and return a tuple `(hit, predval)`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1388
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1389 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1390 pred, predval = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1391 cond,
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1392 "when-ref-true", "when-ref-false",
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1393 "when-ref-exists", "when-ref-not-exists", "when",
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1394 default=_SENTINEL)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1395
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1396 if pred == "when":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1397 # rekursive evaluation of `predval` as the real predicate
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1398 return eval_pred(predval, context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1399 elif pred == "when-ref-true":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1400 refobj = try_get_reference(predval, context, schema, default=None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1401 return bool(refobj)
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1402 elif pred == "when-ref-false":
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1403 refobj = try_get_reference(predval, context, schema, default=None)
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1404 return not bool(refobj)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1405 elif pred == "when-ref-exists":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1406 refobj = try_get_reference(predval, context, schema, default=_SENTINEL)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1407 return refobj is not _SENTINEL
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1408 elif pred == "when-ref-not-exists":
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1409 refobj = try_get_reference(predval, context, schema, default=_SENTINEL)
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1410 return refobj is _SENTINEL
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1411 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1412 raise SchemaError("unknown condition type: {}".format(pred))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1413
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1414
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1415 def eval_pred(pred, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1416 if isinstance(pred, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1417 combinator, combinator_val = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1418 pred,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1419 "not", "all-of", "any-of", "one-of",
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1420 default=None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1421 if combinator:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1422 if combinator == "not":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1423 return not eval_pred(combinator_val, context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1424 elif combinator == "all-of":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1425 if not isinstance(combinator_val, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1426 raise SchemaError("`all-of' requires a list of childs")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1427 for cv in combinator_val:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1428 if not eval_pred(cv, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1429 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1430 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1431 elif combinator == "any-of":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1432 if not isinstance(combinator_val, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1433 raise SchemaError("`any-of' requires a list of childs")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1434 for cv in combinator_val:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1435 if eval_pred(cv, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1436 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1437 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1438 elif combinator == "one-of":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1439 if not isinstance(combinator_val, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1440 raise SchemaError("`one-of' requires a list of childs")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1441 num_true = 0
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1442 for cv in combinator_val:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1443 if eval_pred(cv, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1444 num_true += 1
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1445 # shortcut
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1446 if num_true > 1:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1447 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1448 if num_true == 1:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1449 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1450 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1451 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1452 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1453 raise SchemaError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1454 "unknown logical operator: {}".format(combinator))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1455 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1456 pred_key, pred_val = _get_one_of(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1457 pred,
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1458 "ref-true", "ref-false", "ref-exists", "ref-not-exists",
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1459 "equals",
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1460 default=None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1461 if pred_key == "ref-true":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1462 refobj = try_get_reference(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1463 pred_val, context, schema, default=None)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1464 return bool(refobj)
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1465 elif pred_key == "ref-false":
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1466 refobj = try_get_reference(
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1467 pred_val, context, schema, default=None)
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1468 return not bool(refobj)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1469 elif pred_key == "ref-exists":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1470 refobj = try_get_reference(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1471 pred_val, context, schema, default=_SENTINEL)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1472 return refobj is not _SENTINEL
39
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1473 elif pred_key == "ref-not-exists":
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1474 refobj = try_get_reference(
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1475 pred_val, context, schema, default=_SENTINEL)
78f5ef0ee087 Implement "ref-false", "ref-not-exists", "when-ref-false" and "when-ref-not-exists" in addition to the existing conditions
Franz Glasner <f.glasner@feldmann-mg.com>
parents: 38
diff changeset
1476 return refobj is _SENTINEL
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1477 elif pred_key == "equals":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1478 if not isinstance(pred_val, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1479 raise SchemaError("`equals' requires a list as childs")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1480 if len(pred_val) != 2:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1481 raise SchemaError("`equals' requires a list of len 2")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1482 op1 = eval_comparison_operator_operand(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1483 pred_val[0], context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1484 op2 = eval_comparison_operator_operand(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1485 pred_val[1], context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1486 return op1 == op2
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1487 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1488 raise SchemaError("unknown predicate: {}".format(pred))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1489 elif isinstance(pred, list):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1490 # implicit all-of (aka AND)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1491 for cv in pred:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1492 if not eval_pred(cv, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1493 return False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1494 return True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1495 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1496 return pred
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1497
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1498
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1499 def eval_comparison_operator_operand(op, context, schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1500 if not isinstance(op, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1501 raise SchemaError("an operand must be a dict")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1502 opkey, opval = _get_one_of(op, "ref", "val", "value")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1503 if opkey is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1504 raise SchemaError("no operant given in {!r}".format(op))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1505 if opkey == "ref":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1506 return try_get_reference(opval, context, schema)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1507 elif opkey in ("val", "value"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1508 return opval
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1509 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1510 assert False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1511
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1512
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1513 def try_get_reference(ref, context, schema, default=None):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1514 """Get the object referenced in `ref`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1515
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1516 Use `context` as data/object context and `schema` as the current schema
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1517 context.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1518
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1519 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1520 uri = rfc3986.URIReference.from_string(ref).normalize()
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1521 if not uri.scheme:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1522 uri = uri.copy_with(scheme="object")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1523 if uri.scheme == "object":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1524 if ref.startswith("object#"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1525 for attr in ("authority", "path", "query"):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1526 if getattr(uri, attr, None) is not None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1527 raise SchemaError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1528 "bogus {} in URI reference `{}'".format(attr, ref))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1529 if uri.fragment is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1530 raise SchemaError("fragment required in reference")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1531 if not uri.fragment:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1532 return context.root.root_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1533 elif uri.fragment == '.':
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1534 return context.current_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1535 parts = uri.fragment.split('.') # use '.' separator as in configmix
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1536 if parts[0]:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1537 # absolute
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1538 d = context.root.root_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1539 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1540 # relative
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1541 d = context.current_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1542 parts = parts[1:]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1543 c = context # needed to determine relative object references
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1544 relative_refs_allowed = True
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1545 for part in [urllib.parse.unquote(p) for p in parts]:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1546 if part:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1547 relative_refs_allowed = False
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1548 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1549 d = d[part]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1550 except (KeyError, IndexError, TypeError):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1551 return default
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1552 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1553 if not relative_refs_allowed:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1554 raise SchemaError(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1555 "empty part in path to object reference not allowed")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1556 c = c.safe_parent
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1557 d = c.current_object
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1558 return d
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1559 elif uri.scheme == "schema":
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1560 if not uri.path or (uri.path == SCHEMA_PATH_SELF):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1561 s = schema.SELF
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1562 elif uri.path == SCHEMA_PATH_ROOT:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1563 s = schema.ROOT
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1564 else:
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
1565 s = schema.get_cached_schema(
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
1566 uri.path,
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
1567 load_if_needed=True,
29
68286d27f27d FIX: Allow customization of the data stream loader (get_data_stream())
Franz Glasner <fzglas.hg@dom66.de>
parents: 28
diff changeset
1568 data_stream_loader=context.settings.data_stream_loader,
28
db3491e1b590 Allow to customize the loading of the schema dict
Franz Glasner <fzglas.hg@dom66.de>
parents: 25
diff changeset
1569 schema_loader=context.settings.schema_loader)
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1570 if uri.fragment is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1571 raise SchemaError("fragment required in reference")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1572
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1573 if not uri.fragment.startswith('/'):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1574 raise SchemaError("references to parts of a schema must be absolute (begin with `/')")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1575 if uri.fragment == '/':
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1576 return s
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1577 parts = uri.fragment.split('/')
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1578 parent_for_subschema = s
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1579 for part in [urllib.parse.unquote(p) for p in parts[1:]]:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1580 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1581 v = s[part]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1582 except (KeyError, IndexError, TypeError):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1583 return default
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1584 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1585 if isinstance(v, _Schema):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1586 pass
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1587 elif isinstance(v, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1588 s = _Schema(parent_for_subschema, False, v)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1589 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1590 # need not try further
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1591 return default
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1592 return s
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1593 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1594 raise SchemaError("Unknown schema reference scheme: {}".format(uri.scheme))
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1595
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1596
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1597 _DEL_VALUE = '{{::DEL::}}'
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1598 """Sigil to mark keys to be deleted in the target when merging"""
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1599
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1600
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1601 def _merge(user, default):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1602 """Logically merge the configuration in `user` into `default`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1603
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1604 :param dict user:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1605 the new configuration that will be logically merged
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1606 into `default`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1607 :param dict default:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1608 the base configuration where `user` is logically merged into
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1609 :returns: `user` with the necessary amendments from `default`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1610 If `user` is ``None`` then `default` is returned.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1611
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1612 .. note:: Implementation: The configuration in `user` is
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1613 augmented/changed **inplace**.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1614
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1615 If a value in `user` is equal to :data:`._DEL_VALUE`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1616 (``{{::DEL::}}``) the corresponding key will be deleted from the
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1617 merged output.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1618
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1619 From http://stackoverflow.com/questions/823196/yaml-merge-in-python
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1620
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1621 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1622 if user is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1623 _filter_deletions(default)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1624 return default
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1625 if isinstance(user, dict) and isinstance(default, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1626 for k, v in default.items():
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1627 if k in user:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1628 if user[k] == _DEL_VALUE:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1629 # do not copy and delete the marker
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1630 del user[k]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1631 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1632 user[k] = _merge_item(user[k], v)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1633 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1634 user[k] = v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1635 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1636 raise SchemaError("can only merge two dicts on top-level")
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1637 _filter_deletions(user)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1638 return user
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1639
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1640
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1641 def _merge_item(user, default):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1642 """Recursion helper for :func:`._merge`
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1643
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1644 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1645 if isinstance(user, dict) and isinstance(default, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1646 for k, v in default.items():
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1647 if k in user:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1648 if user[k] == _DEL_VALUE:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1649 # do not copy and delete the marker
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1650 del user[k]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1651 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1652 user[k] = _merge_item(user[k], v)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1653 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1654 user[k] = v
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1655 elif isinstance(user, (list, tuple)) and isinstance(default, (list, tuple)):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1656 for idx, v in enumerate(default):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1657 user.insert(idx, v)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1658 return user
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1659
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1660
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1661 def _filter_deletions(d):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1662 """Recursively filter deletions in the dict `d`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1663
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1664 Deletions have values that equal :data:`._DEL_VALUE`.
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1665
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1666 """
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1667 if not isinstance(d, dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1668 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1669 # use a copy of the items because we change `d` while iterating
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1670 for k, v in list(d.items()):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1671 if v == _DEL_VALUE:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1672 del d[k]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1673 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1674 if isinstance(d[k], dict):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1675 _filter_deletions(d[k])
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1676
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1677
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1678 def _log_problem_cause_all(logger, loglevel, level, problems):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1679 if not problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1680 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1681 for pr in problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1682 logger.log(loglevel, "%s> %r", "-"*((level*2)+2), pr)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1683 _log_problem_cause_all(logger, loglevel, level+1, pr.cause)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1684
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1685
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1686 def _build_problems_by_level_and_depth(by_level, by_depth, level, problems):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1687 for pr in problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1688 if not pr.cause:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1689 continue
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1690 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1691 prl = by_level[level]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1692 except LookupError:
9
Franz Glasner <fzglas.hg@dom66.de>
parents: 5
diff changeset
1693 prl = []
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1694 by_level[level] = prl
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1695 prl.append(pr)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1696
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1697 depth = pr.context.depth
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1698 try:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1699 prd = by_depth[depth]
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1700 except LookupError:
9
Franz Glasner <fzglas.hg@dom66.de>
parents: 5
diff changeset
1701 prd = []
5
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1702 by_depth[depth] = prd
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1703 prd.append(pr)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1704 _build_problems_by_level_and_depth(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1705 by_level, by_depth, level+1, pr.cause)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1706
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1707
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1708 def _log_problem_cause(logger, loglevel, max_level, max_depth, level, problems):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1709 for pr in problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1710 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1711 # Check whether we will start logging from this level downwards
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1712 # all problems
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1713 #
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1714 if max_level is None or level == max_level:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1715 new_max_level = None # trigger logging
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1716 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1717 new_max_level = max_level
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1718 if max_depth is None or max_depth == pr.context.depth:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1719 new_max_depth = None # trigger logging
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1720 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1721 new_max_depth = max_depth
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1722 if new_max_level is None or new_max_depth is None:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1723 logger.log(loglevel, "%s> %r", "-"*((level*2)+2), pr)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1724 if pr.cause:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1725 _log_problem_cause(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1726 logger, loglevel,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1727 new_max_level, new_max_depth,
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1728 level+1, pr.cause)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1729
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1730
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1731 def log_problem_cause(logger, loglevel, debug, level, problems):
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1732 if not problems:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1733 return
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1734 if debug:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1735 _log_problem_cause_all(logger, loglevel, level, problems)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1736 else:
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1737 by_level = {} # to determine maximum problem nesting level
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1738 by_depth = {} # to determine maximum context nexting level
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1739 _build_problems_by_level_and_depth(by_level, by_depth, level, problems)
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1740
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1741 max_level = max(by_level.keys())
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1742 max_depth = max(by_depth.keys())
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1743
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1744 _log_problem_cause(
84dfd1a94926 Add the existing implementation.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1745 logger, loglevel, max_level, max_depth, level, problems)