Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/openapi_schema_validator/_keywords.py: 25%
126 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:30 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:30 +0000
1from copy import deepcopy
2from typing import Any
3from typing import Dict
4from typing import Hashable
5from typing import ItemsView
6from typing import Iterator
7from typing import List
8from typing import Mapping
9from typing import Union
11from jsonschema._keywords import allOf as _allOf
12from jsonschema._keywords import anyOf as _anyOf
13from jsonschema._keywords import oneOf as _oneOf
14from jsonschema._utils import extras_msg
15from jsonschema._utils import find_additional_properties
16from jsonschema.exceptions import FormatError
17from jsonschema.exceptions import ValidationError
18from jsonschema.protocols import Validator
21def handle_discriminator(
22 validator: Validator, _: Any, instance: Any, schema: Mapping[Hashable, Any]
23) -> Iterator[ValidationError]:
24 """
25 Handle presence of discriminator in anyOf, oneOf and allOf.
26 The behaviour is the same in all 3 cases because at most 1 schema will match.
27 """
28 discriminator = schema["discriminator"]
29 prop_name = discriminator["propertyName"]
30 prop_value = instance.get(prop_name)
31 if not prop_value:
32 # instance is missing $propertyName
33 yield ValidationError(
34 f"{instance!r} does not contain discriminating property {prop_name!r}",
35 context=[],
36 )
37 return
39 # Use explicit mapping if available, otherwise try implicit value
40 ref = (
41 discriminator.get("mapping", {}).get(prop_value)
42 or f"#/components/schemas/{prop_value}"
43 )
45 if not isinstance(ref, str):
46 # this is a schema error
47 yield ValidationError(
48 "{!r} mapped value for {!r} should be a string, was {!r}".format(
49 instance, prop_value, ref
50 ),
51 context=[],
52 )
53 return
55 try:
56 validator._validate_reference(ref=ref, instance=instance)
57 except:
58 yield ValidationError(
59 f"{instance!r} reference {ref!r} could not be resolved",
60 context=[],
61 )
62 return
64 yield from validator.descend(instance, {"$ref": ref})
67def anyOf(
68 validator: Validator,
69 anyOf: List[Mapping[Hashable, Any]],
70 instance: Any,
71 schema: Mapping[Hashable, Any],
72) -> Iterator[ValidationError]:
73 if "discriminator" not in schema:
74 yield from _anyOf(validator, anyOf, instance, schema)
75 else:
76 yield from handle_discriminator(validator, anyOf, instance, schema)
79def oneOf(
80 validator: Validator,
81 oneOf: List[Mapping[Hashable, Any]],
82 instance: Any,
83 schema: Mapping[Hashable, Any],
84) -> Iterator[ValidationError]:
85 if "discriminator" not in schema:
86 yield from _oneOf(validator, oneOf, instance, schema)
87 else:
88 yield from handle_discriminator(validator, oneOf, instance, schema)
91def allOf(
92 validator: Validator,
93 allOf: List[Mapping[Hashable, Any]],
94 instance: Any,
95 schema: Mapping[Hashable, Any],
96) -> Iterator[ValidationError]:
97 if "discriminator" not in schema:
98 yield from _allOf(validator, allOf, instance, schema)
99 else:
100 yield from handle_discriminator(validator, allOf, instance, schema)
103def type(
104 validator: Validator,
105 data_type: str,
106 instance: Any,
107 schema: Mapping[Hashable, Any],
108) -> Iterator[ValidationError]:
109 if instance is None:
110 # nullable implementation based on OAS 3.0.3
111 # * nullable is only meaningful if its value is true
112 # * nullable: true is only meaningful in combination with a type
113 # assertion specified in the same Schema Object.
114 # * nullable: true operates within a single Schema Object
115 if "nullable" in schema and schema["nullable"] == True:
116 return
117 yield ValidationError("None for not nullable")
119 if not validator.is_type(instance, data_type):
120 data_repr = repr(data_type)
121 yield ValidationError(f"{instance!r} is not of type {data_repr}")
124def format(
125 validator: Validator,
126 format: str,
127 instance: Any,
128 schema: Mapping[Hashable, Any],
129) -> Iterator[ValidationError]:
130 if instance is None:
131 return
133 if validator.format_checker is not None:
134 try:
135 validator.format_checker.check(instance, format)
136 except FormatError as error:
137 yield ValidationError(str(error), cause=error.cause)
140def items(
141 validator: Validator,
142 items: Mapping[Hashable, Any],
143 instance: Any,
144 schema: Mapping[Hashable, Any],
145) -> Iterator[ValidationError]:
146 if not validator.is_type(instance, "array"):
147 return
149 for index, item in enumerate(instance):
150 yield from validator.descend(item, items, path=index)
153def required(
154 validator: Validator,
155 required: List[str],
156 instance: Any,
157 schema: Mapping[Hashable, Any],
158) -> Iterator[ValidationError]:
159 if not validator.is_type(instance, "object"):
160 return
161 for property in required:
162 if property not in instance:
163 prop_schema = schema.get("properties", {}).get(property)
164 if prop_schema:
165 read_only = prop_schema.get("readOnly", False)
166 write_only = prop_schema.get("writeOnly", False)
167 if (
168 getattr(validator, "write", True)
169 and read_only
170 or getattr(validator, "read", True)
171 and write_only
172 ):
173 continue
174 yield ValidationError(f"{property!r} is a required property")
177def read_required(
178 validator: Validator,
179 required: List[str],
180 instance: Any,
181 schema: Mapping[Hashable, Any],
182) -> Iterator[ValidationError]:
183 if not validator.is_type(instance, "object"):
184 return
185 for property in required:
186 if property not in instance:
187 prop_schema = schema.get("properties", {}).get(property)
188 if prop_schema:
189 write_only = prop_schema.get("writeOnly", False)
190 if getattr(validator, "read", True) and write_only:
191 continue
192 yield ValidationError(f"{property!r} is a required property")
195def write_required(
196 validator: Validator,
197 required: List[str],
198 instance: Any,
199 schema: Mapping[Hashable, Any],
200) -> Iterator[ValidationError]:
201 if not validator.is_type(instance, "object"):
202 return
203 for property in required:
204 if property not in instance:
205 prop_schema = schema.get("properties", {}).get(property)
206 if prop_schema:
207 read_only = prop_schema.get("readOnly", False)
208 if read_only:
209 continue
210 yield ValidationError(f"{property!r} is a required property")
213def additionalProperties(
214 validator: Validator,
215 aP: Union[Mapping[Hashable, Any], bool],
216 instance: Any,
217 schema: Mapping[Hashable, Any],
218) -> Iterator[ValidationError]:
219 if not validator.is_type(instance, "object"):
220 return
222 extras = set(find_additional_properties(instance, schema))
224 if not extras:
225 return
227 if validator.is_type(aP, "object"):
228 for extra in extras:
229 for error in validator.descend(instance[extra], aP, path=extra):
230 yield error
231 elif validator.is_type(aP, "boolean"):
232 if not aP:
233 error = "Additional properties are not allowed (%s %s unexpected)"
234 yield ValidationError(error % extras_msg(extras))
237def readOnly(
238 validator: Validator,
239 ro: bool,
240 instance: Any,
241 schema: Mapping[Hashable, Any],
242) -> Iterator[ValidationError]:
243 if not getattr(validator, "write", True) or not ro:
244 return
246 yield ValidationError(f"Tried to write read-only property with {instance}")
249def writeOnly(
250 validator: Validator,
251 wo: bool,
252 instance: Any,
253 schema: Mapping[Hashable, Any],
254) -> Iterator[ValidationError]:
255 if not getattr(validator, "read", True) or not wo:
256 return
258 yield ValidationError(f"Tried to read write-only property with {instance}")
261def not_implemented(
262 validator: Validator,
263 value: Any,
264 instance: Any,
265 schema: Mapping[Hashable, Any],
266) -> Iterator[ValidationError]:
267 return
268 yield