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

238 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

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 else: 

206 if validator.is_type(instance, type): 

207 return 

208 else: 

209 reprs = [] 

210 for type in types: 

211 try: 

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

213 except Exception: 

214 reprs.append(repr(type)) 

215 yield ValidationError( 

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

217 context=all_errors, 

218 ) 

219 

220 

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

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

223 return 

224 

225 if not any( 

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

227 for element in instance 

228 ): 

229 yield ValidationError( 

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

231 ) 

232 

233 

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

235 resolved = lookup_recursive_ref(validator._resolver) 

236 yield from validator.descend( 

237 instance, 

238 resolved.contents, 

239 resolver=resolved.resolver, 

240 ) 

241 

242 

243def find_evaluated_item_indexes_by_schema(validator, instance, schema): 

244 """ 

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

246 

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

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

249 """ 

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

251 return [] 

252 evaluated_indexes = [] 

253 

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

255 if ref is not None: 

256 resolved = validator._resolver.lookup(ref) 

257 evaluated_indexes.extend( 

258 find_evaluated_item_indexes_by_schema( 

259 validator.evolve( 

260 schema=resolved.contents, 

261 _resolver=resolved.resolver, 

262 ), 

263 instance, 

264 resolved.contents, 

265 ), 

266 ) 

267 

268 if "$recursiveRef" in schema: 

269 resolved = lookup_recursive_ref(validator._resolver) 

270 evaluated_indexes.extend( 

271 find_evaluated_item_indexes_by_schema( 

272 validator.evolve( 

273 schema=resolved.contents, 

274 _resolver=resolved.resolver, 

275 ), 

276 instance, 

277 resolved.contents, 

278 ), 

279 ) 

280 

281 if "items" in schema: 

282 if "additionalItems" in schema: 

283 return list(range(0, len(instance))) 

284 

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

286 return list(range(0, len(instance))) 

287 evaluated_indexes += list(range(0, len(schema["items"]))) 

288 

289 if "if" in schema: 

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

291 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

293 ) 

294 if "then" in schema: 

295 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

297 ) 

298 else: 

299 if "else" in schema: 

300 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

302 ) 

303 

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

305 if keyword in schema: 

306 for k, v in enumerate(instance): 

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

308 evaluated_indexes.append(k) 

309 

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

311 if keyword in schema: 

312 for subschema in schema[keyword]: 

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

314 if errs is None: 

315 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

316 validator, instance, subschema, 

317 ) 

318 

319 return evaluated_indexes 

320 

321 

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

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

324 return 

325 evaluated_item_indexes = find_evaluated_item_indexes_by_schema( 

326 validator, instance, schema, 

327 ) 

328 unevaluated_items = [ 

329 item for index, item in enumerate(instance) 

330 if index not in evaluated_item_indexes 

331 ] 

332 if unevaluated_items: 

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

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

335 

336 

337def find_evaluated_property_keys_by_schema(validator, instance, schema): 

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

339 return [] 

340 evaluated_keys = [] 

341 

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

343 if ref is not None: 

344 resolved = validator._resolver.lookup(ref) 

345 evaluated_keys.extend( 

346 find_evaluated_property_keys_by_schema( 

347 validator.evolve( 

348 schema=resolved.contents, 

349 _resolver=resolved.resolver, 

350 ), 

351 instance, 

352 resolved.contents, 

353 ), 

354 ) 

355 

356 if "$recursiveRef" in schema: 

357 resolved = lookup_recursive_ref(validator._resolver) 

358 evaluated_keys.extend( 

359 find_evaluated_property_keys_by_schema( 

360 validator.evolve( 

361 schema=resolved.contents, 

362 _resolver=resolved.resolver, 

363 ), 

364 instance, 

365 resolved.contents, 

366 ), 

367 ) 

368 

369 for keyword in [ 

370 "properties", "additionalProperties", "unevaluatedProperties", 

371 ]: 

372 if keyword in schema: 

373 schema_value = schema[keyword] 

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

375 evaluated_keys += instance.keys() 

376 

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

378 for property in schema_value: 

379 if property in instance: 

380 evaluated_keys.append(property) 

381 

382 if "patternProperties" in schema: 

383 for property in instance: 

384 for pattern in schema["patternProperties"]: 

385 if re.search(pattern, property): 

386 evaluated_keys.append(property) 

387 

388 if "dependentSchemas" in schema: 

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

390 if property not in instance: 

391 continue 

392 evaluated_keys += find_evaluated_property_keys_by_schema( 

393 validator, instance, subschema, 

394 ) 

395 

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

397 if keyword in schema: 

398 for subschema in schema[keyword]: 

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

400 if errs is None: 

401 evaluated_keys += find_evaluated_property_keys_by_schema( 

402 validator, instance, subschema, 

403 ) 

404 

405 if "if" in schema: 

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

407 evaluated_keys += find_evaluated_property_keys_by_schema( 

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

409 ) 

410 if "then" in schema: 

411 evaluated_keys += find_evaluated_property_keys_by_schema( 

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

413 ) 

414 else: 

415 if "else" in schema: 

416 evaluated_keys += find_evaluated_property_keys_by_schema( 

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

418 ) 

419 

420 return evaluated_keys 

421 

422 

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

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

425 return 

426 evaluated_keys = find_evaluated_property_keys_by_schema( 

427 validator, instance, schema, 

428 ) 

429 unevaluated_keys = [] 

430 for property in instance: 

431 if property not in evaluated_keys: 

432 for _ in validator.descend( 

433 instance[property], 

434 uP, 

435 path=property, 

436 schema_path=property, 

437 ): 

438 # FIXME: Include context for each unevaluated property 

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

440 unevaluated_keys.append(property) 

441 

442 if unevaluated_keys: 

443 if uP is False: 

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

445 extras = sorted(unevaluated_keys, key=str) 

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

447 else: 

448 error = ( 

449 "Unevaluated properties are not valid under " 

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

451 ) 

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