Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jsonschema/_legacy_keywords.py: 9%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

238 statements  

1import re 

2 

3from referencing.jsonschema import lookup_recursive_ref 

4 

5from jsonschema import _utils 

6from jsonschema.exceptions import ValidationError 

7 

8 

9def ignore_ref_siblings(schema): 

10 """ 

11 Ignore siblings of ``$ref`` if it is present. 

12 

13 Otherwise, return all keywords. 

14 

15 Suitable for use with `create`'s ``applicable_validators`` argument. 

16 """ 

17 ref = schema.get("$ref") 

18 if ref is not None: 

19 return [("$ref", ref)] 

20 else: 

21 return schema.items() 

22 

23 

24def dependencies_draft3(validator, dependencies, instance, schema): 

25 if not validator.is_type(instance, "object"): 

26 return 

27 

28 for property, dependency in dependencies.items(): 

29 if property not in instance: 

30 continue 

31 

32 if validator.is_type(dependency, "object"): 

33 yield from validator.descend( 

34 instance, dependency, schema_path=property, 

35 ) 

36 elif validator.is_type(dependency, "string"): 

37 if dependency not in instance: 

38 message = f"{dependency!r} is a dependency of {property!r}" 

39 yield ValidationError(message) 

40 else: 

41 for each in dependency: 

42 if each not in instance: 

43 message = f"{each!r} is a dependency of {property!r}" 

44 yield ValidationError(message) 

45 

46 

47def dependencies_draft4_draft6_draft7( 

48 validator, 

49 dependencies, 

50 instance, 

51 schema, 

52): 

53 """ 

54 Support for the ``dependencies`` keyword from pre-draft 2019-09. 

55 

56 In later drafts, the keyword was split into separate 

57 ``dependentRequired`` and ``dependentSchemas`` validators. 

58 """ 

59 if not validator.is_type(instance, "object"): 

60 return 

61 

62 for property, dependency in dependencies.items(): 

63 if property not in instance: 

64 continue 

65 

66 if validator.is_type(dependency, "array"): 

67 for each in dependency: 

68 if each not in instance: 

69 message = f"{each!r} is a dependency of {property!r}" 

70 yield ValidationError(message) 

71 else: 

72 yield from validator.descend( 

73 instance, dependency, schema_path=property, 

74 ) 

75 

76 

77def disallow_draft3(validator, disallow, instance, schema): 

78 for disallowed in _utils.ensure_list(disallow): 

79 if validator.evolve(schema={"type": [disallowed]}).is_valid(instance): 

80 message = f"{disallowed!r} is disallowed for {instance!r}" 

81 yield ValidationError(message) 

82 

83 

84def extends_draft3(validator, extends, instance, schema): 

85 if validator.is_type(extends, "object"): 

86 yield from validator.descend(instance, extends) 

87 return 

88 for index, subschema in enumerate(extends): 

89 yield from validator.descend(instance, subschema, schema_path=index) 

90 

91 

92def items_draft3_draft4(validator, items, instance, schema): 

93 if not validator.is_type(instance, "array"): 

94 return 

95 

96 if validator.is_type(items, "object"): 

97 for index, item in enumerate(instance): 

98 yield from validator.descend(item, items, path=index) 

99 else: 

100 for (index, item), subschema in zip(enumerate(instance), items): 

101 yield from validator.descend( 

102 item, subschema, path=index, schema_path=index, 

103 ) 

104 

105 

106def additionalItems(validator, aI, instance, schema): 

107 if ( 

108 not validator.is_type(instance, "array") 

109 or validator.is_type(schema.get("items", {}), "object") 

110 ): 

111 return 

112 

113 len_items = len(schema.get("items", [])) 

114 if validator.is_type(aI, "object"): 

115 for index, item in enumerate(instance[len_items:], start=len_items): 

116 yield from validator.descend(item, aI, path=index) 

117 elif not aI and len(instance) > len(schema.get("items", [])): 

118 error = "Additional items are not allowed (%s %s unexpected)" 

119 yield ValidationError( 

120 error % _utils.extras_msg(instance[len(schema.get("items", [])):]), 

121 ) 

122 

123 

124def items_draft6_draft7_draft201909(validator, items, instance, schema): 

125 if not validator.is_type(instance, "array"): 

126 return 

127 

128 if validator.is_type(items, "array"): 

129 for (index, item), subschema in zip(enumerate(instance), items): 

130 yield from validator.descend( 

131 item, subschema, path=index, schema_path=index, 

132 ) 

133 else: 

134 for index, item in enumerate(instance): 

135 yield from validator.descend(item, items, path=index) 

136 

137 

138def minimum_draft3_draft4(validator, minimum, instance, schema): 

139 if not validator.is_type(instance, "number"): 

140 return 

141 

142 if schema.get("exclusiveMinimum", False): 

143 failed = instance <= minimum 

144 cmp = "less than or equal to" 

145 else: 

146 failed = instance < minimum 

147 cmp = "less than" 

148 

149 if failed: 

150 message = f"{instance!r} is {cmp} the minimum of {minimum!r}" 

151 yield ValidationError(message) 

152 

153 

154def maximum_draft3_draft4(validator, maximum, instance, schema): 

155 if not validator.is_type(instance, "number"): 

156 return 

157 

158 if schema.get("exclusiveMaximum", False): 

159 failed = instance >= maximum 

160 cmp = "greater than or equal to" 

161 else: 

162 failed = instance > maximum 

163 cmp = "greater than" 

164 

165 if failed: 

166 message = f"{instance!r} is {cmp} the maximum of {maximum!r}" 

167 yield ValidationError(message) 

168 

169 

170def properties_draft3(validator, properties, instance, schema): 

171 if not validator.is_type(instance, "object"): 

172 return 

173 

174 for property, subschema in properties.items(): 

175 if property in instance: 

176 yield from validator.descend( 

177 instance[property], 

178 subschema, 

179 path=property, 

180 schema_path=property, 

181 ) 

182 elif subschema.get("required", False): 

183 error = ValidationError(f"{property!r} is a required property") 

184 error._set( 

185 validator="required", 

186 validator_value=subschema["required"], 

187 instance=instance, 

188 schema=schema, 

189 ) 

190 error.path.appendleft(property) 

191 error.schema_path.extend([property, "required"]) 

192 yield error 

193 

194 

195def type_draft3(validator, types, instance, schema): 

196 types = _utils.ensure_list(types) 

197 

198 all_errors = [] 

199 for index, type in enumerate(types): 

200 if validator.is_type(type, "object"): 

201 errors = list(validator.descend(instance, type, schema_path=index)) 

202 if not errors: 

203 return 

204 all_errors.extend(errors) 

205 elif validator.is_type(instance, type): 

206 return 

207 

208 reprs = [] 

209 for type in types: 

210 try: 

211 reprs.append(repr(type["name"])) 

212 except Exception: # noqa: BLE001 

213 reprs.append(repr(type)) 

214 yield ValidationError( 

215 f"{instance!r} is not of type {', '.join(reprs)}", 

216 context=all_errors, 

217 ) 

218 

219 

220def contains_draft6_draft7(validator, contains, instance, schema): 

221 if not validator.is_type(instance, "array"): 

222 return 

223 

224 if not any( 

225 validator.evolve(schema=contains).is_valid(element) 

226 for element in instance 

227 ): 

228 yield ValidationError( 

229 f"None of {instance!r} are valid under the given schema", 

230 ) 

231 

232 

233def recursiveRef(validator, recursiveRef, instance, schema): 

234 resolved = lookup_recursive_ref(validator._resolver) 

235 yield from validator.descend( 

236 instance, 

237 resolved.contents, 

238 resolver=resolved.resolver, 

239 ) 

240 

241 

242def find_evaluated_item_indexes_by_schema(validator, instance, schema): 

243 """ 

244 Get all indexes of items that get evaluated under the current schema. 

245 

246 Covers all keywords related to unevaluatedItems: items, prefixItems, if, 

247 then, else, contains, unevaluatedItems, allOf, oneOf, anyOf 

248 """ 

249 if validator.is_type(schema, "boolean"): 

250 return [] 

251 evaluated_indexes = [] 

252 

253 ref = schema.get("$ref") 

254 if ref is not None: 

255 resolved = validator._resolver.lookup(ref) 

256 evaluated_indexes.extend( 

257 find_evaluated_item_indexes_by_schema( 

258 validator.evolve( 

259 schema=resolved.contents, 

260 _resolver=resolved.resolver, 

261 ), 

262 instance, 

263 resolved.contents, 

264 ), 

265 ) 

266 

267 if "$recursiveRef" in schema: 

268 resolved = lookup_recursive_ref(validator._resolver) 

269 evaluated_indexes.extend( 

270 find_evaluated_item_indexes_by_schema( 

271 validator.evolve( 

272 schema=resolved.contents, 

273 _resolver=resolved.resolver, 

274 ), 

275 instance, 

276 resolved.contents, 

277 ), 

278 ) 

279 

280 if "items" in schema: 

281 if "additionalItems" in schema: 

282 return list(range(len(instance))) 

283 

284 if validator.is_type(schema["items"], "object"): 

285 return list(range(len(instance))) 

286 evaluated_indexes += list(range(len(schema["items"]))) 

287 

288 if "if" in schema: 

289 if validator.evolve(schema=schema["if"]).is_valid(instance): 

290 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

291 validator, instance, schema["if"], 

292 ) 

293 if "then" in schema: 

294 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

295 validator, instance, schema["then"], 

296 ) 

297 elif "else" in schema: 

298 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

299 validator, instance, schema["else"], 

300 ) 

301 

302 for keyword in ["contains", "unevaluatedItems"]: 

303 if keyword in schema: 

304 for k, v in enumerate(instance): 

305 if validator.evolve(schema=schema[keyword]).is_valid(v): 

306 evaluated_indexes.append(k) 

307 

308 for keyword in ["allOf", "oneOf", "anyOf"]: 

309 if keyword in schema: 

310 for subschema in schema[keyword]: 

311 errs = next(validator.descend(instance, subschema), None) 

312 if errs is None: 

313 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

314 validator, instance, subschema, 

315 ) 

316 

317 return evaluated_indexes 

318 

319 

320def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema): 

321 if not validator.is_type(instance, "array"): 

322 return 

323 evaluated_item_indexes = find_evaluated_item_indexes_by_schema( 

324 validator, instance, schema, 

325 ) 

326 unevaluated_items = [ 

327 item for index, item in enumerate(instance) 

328 if index not in evaluated_item_indexes 

329 ] 

330 if unevaluated_items: 

331 error = "Unevaluated items are not allowed (%s %s unexpected)" 

332 yield ValidationError(error % _utils.extras_msg(unevaluated_items)) 

333 

334 

335def find_evaluated_property_keys_by_schema(validator, instance, schema): 

336 if validator.is_type(schema, "boolean"): 

337 return [] 

338 evaluated_keys = [] 

339 

340 ref = schema.get("$ref") 

341 if ref is not None: 

342 resolved = validator._resolver.lookup(ref) 

343 evaluated_keys.extend( 

344 find_evaluated_property_keys_by_schema( 

345 validator.evolve( 

346 schema=resolved.contents, 

347 _resolver=resolved.resolver, 

348 ), 

349 instance, 

350 resolved.contents, 

351 ), 

352 ) 

353 

354 if "$recursiveRef" in schema: 

355 resolved = lookup_recursive_ref(validator._resolver) 

356 evaluated_keys.extend( 

357 find_evaluated_property_keys_by_schema( 

358 validator.evolve( 

359 schema=resolved.contents, 

360 _resolver=resolved.resolver, 

361 ), 

362 instance, 

363 resolved.contents, 

364 ), 

365 ) 

366 

367 for keyword in [ 

368 "properties", "additionalProperties", "unevaluatedProperties", 

369 ]: 

370 if keyword in schema: 

371 schema_value = schema[keyword] 

372 if validator.is_type(schema_value, "boolean") and schema_value: 

373 evaluated_keys += instance.keys() 

374 

375 elif validator.is_type(schema_value, "object"): 

376 for property in schema_value: 

377 if property in instance: 

378 evaluated_keys.append(property) 

379 

380 if "patternProperties" in schema: 

381 for property in instance: 

382 for pattern in schema["patternProperties"]: 

383 if re.search(pattern, property): 

384 evaluated_keys.append(property) 

385 

386 if "dependentSchemas" in schema: 

387 for property, subschema in schema["dependentSchemas"].items(): 

388 if property not in instance: 

389 continue 

390 evaluated_keys += find_evaluated_property_keys_by_schema( 

391 validator, instance, subschema, 

392 ) 

393 

394 for keyword in ["allOf", "oneOf", "anyOf"]: 

395 if keyword in schema: 

396 for subschema in schema[keyword]: 

397 errs = next(validator.descend(instance, subschema), None) 

398 if errs is None: 

399 evaluated_keys += find_evaluated_property_keys_by_schema( 

400 validator, instance, subschema, 

401 ) 

402 

403 if "if" in schema: 

404 if validator.evolve(schema=schema["if"]).is_valid(instance): 

405 evaluated_keys += find_evaluated_property_keys_by_schema( 

406 validator, instance, schema["if"], 

407 ) 

408 if "then" in schema: 

409 evaluated_keys += find_evaluated_property_keys_by_schema( 

410 validator, instance, schema["then"], 

411 ) 

412 elif "else" in schema: 

413 evaluated_keys += find_evaluated_property_keys_by_schema( 

414 validator, instance, schema["else"], 

415 ) 

416 

417 return evaluated_keys 

418 

419 

420def unevaluatedProperties_draft2019(validator, uP, instance, schema): 

421 if not validator.is_type(instance, "object"): 

422 return 

423 evaluated_keys = find_evaluated_property_keys_by_schema( 

424 validator, instance, schema, 

425 ) 

426 unevaluated_keys = [] 

427 for property in instance: 

428 if property not in evaluated_keys: 

429 for _ in validator.descend( 

430 instance[property], 

431 uP, 

432 path=property, 

433 schema_path=property, 

434 ): 

435 # FIXME: Include context for each unevaluated property 

436 # indicating why it's invalid under the subschema. 

437 unevaluated_keys.append(property) # noqa: PERF401 

438 

439 if unevaluated_keys: 

440 if uP is False: 

441 error = "Unevaluated properties are not allowed (%s %s unexpected)" 

442 extras = sorted(unevaluated_keys, key=str) 

443 yield ValidationError(error % _utils.extras_msg(extras)) 

444 else: 

445 error = ( 

446 "Unevaluated properties are not valid under " 

447 "the given schema (%s %s unevaluated and invalid)" 

448 ) 

449 yield ValidationError(error % _utils.extras_msg(unevaluated_keys))