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

179 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-01 06:54 +0000

1from jsonschema import _utils 

2from jsonschema.exceptions import ValidationError 

3 

4 

5def id_of_ignore_ref(property="$id"): 

6 def id_of(schema): 

7 """ 

8 Ignore an ``$id`` sibling of ``$ref`` if it is present. 

9 

10 Otherwise, return the ID of the given schema. 

11 """ 

12 if schema is True or schema is False or "$ref" in schema: 

13 return "" 

14 return schema.get(property, "") 

15 return id_of 

16 

17 

18def ignore_ref_siblings(schema): 

19 """ 

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

21 

22 Otherwise, return all keywords. 

23 

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

25 """ 

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

27 if ref is not None: 

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

29 else: 

30 return schema.items() 

31 

32 

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

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

35 return 

36 

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

38 if property not in instance: 

39 continue 

40 

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

42 yield from validator.descend( 

43 instance, dependency, schema_path=property, 

44 ) 

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

46 if dependency not in instance: 

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

48 yield ValidationError(message) 

49 else: 

50 for each in dependency: 

51 if each not in instance: 

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

53 yield ValidationError(message) 

54 

55 

56def dependencies_draft4_draft6_draft7( 

57 validator, 

58 dependencies, 

59 instance, 

60 schema, 

61): 

62 """ 

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

64 

65 In later drafts, the keyword was split into separate 

66 ``dependentRequired`` and ``dependentSchemas`` validators. 

67 """ 

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

69 return 

70 

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

72 if property not in instance: 

73 continue 

74 

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

76 for each in dependency: 

77 if each not in instance: 

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

79 yield ValidationError(message) 

80 else: 

81 yield from validator.descend( 

82 instance, dependency, schema_path=property, 

83 ) 

84 

85 

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

87 for disallowed in _utils.ensure_list(disallow): 

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

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

90 yield ValidationError(message) 

91 

92 

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

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

95 yield from validator.descend(instance, extends) 

96 return 

97 for index, subschema in enumerate(extends): 

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

99 

100 

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

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

103 return 

104 

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

106 for index, item in enumerate(instance): 

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

108 else: 

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

110 yield from validator.descend( 

111 item, subschema, path=index, schema_path=index, 

112 ) 

113 

114 

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

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

117 return 

118 

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

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

121 yield from validator.descend( 

122 item, subschema, path=index, schema_path=index, 

123 ) 

124 else: 

125 for index, item in enumerate(instance): 

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

127 

128 

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

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

131 return 

132 

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

134 failed = instance <= minimum 

135 cmp = "less than or equal to" 

136 else: 

137 failed = instance < minimum 

138 cmp = "less than" 

139 

140 if failed: 

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

142 yield ValidationError(message) 

143 

144 

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

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

147 return 

148 

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

150 failed = instance >= maximum 

151 cmp = "greater than or equal to" 

152 else: 

153 failed = instance > maximum 

154 cmp = "greater than" 

155 

156 if failed: 

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

158 yield ValidationError(message) 

159 

160 

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

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

163 return 

164 

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

166 if property in instance: 

167 yield from validator.descend( 

168 instance[property], 

169 subschema, 

170 path=property, 

171 schema_path=property, 

172 ) 

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

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

175 error._set( 

176 validator="required", 

177 validator_value=subschema["required"], 

178 instance=instance, 

179 schema=schema, 

180 ) 

181 error.path.appendleft(property) 

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

183 yield error 

184 

185 

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

187 types = _utils.ensure_list(types) 

188 

189 all_errors = [] 

190 for index, type in enumerate(types): 

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

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

193 if not errors: 

194 return 

195 all_errors.extend(errors) 

196 else: 

197 if validator.is_type(instance, type): 

198 return 

199 else: 

200 reprs = [] 

201 for type in types: 

202 try: 

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

204 except Exception: 

205 reprs.append(repr(type)) 

206 yield ValidationError( 

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

208 context=all_errors, 

209 ) 

210 

211 

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

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

214 return 

215 

216 if not any( 

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

218 for element in instance 

219 ): 

220 yield ValidationError( 

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

222 ) 

223 

224 

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

226 lookup_url, target = validator.resolver.resolution_scope, validator.schema 

227 

228 for each in reversed(validator.resolver._scopes_stack[1:]): 

229 lookup_url, next_target = validator.resolver.resolve(each) 

230 if next_target.get("$recursiveAnchor"): 

231 target = next_target 

232 else: 

233 break 

234 

235 fragment = recursiveRef.lstrip("#") 

236 subschema = validator.resolver.resolve_fragment(target, fragment) 

237 # FIXME: This is gutted (and not calling .descend) because it can trigger 

238 # recursion errors, so there's a bug here. Re-enable the tests to 

239 # see it. 

240 subschema 

241 return [] 

242 

243 

244def find_evaluated_item_indexes_by_schema(validator, instance, schema): 

245 """ 

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

247 

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

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

250 """ 

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

252 return [] 

253 evaluated_indexes = [] 

254 

255 if "additionalItems" in schema: 

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

257 

258 if "$ref" in schema: 

259 scope, resolved = validator.resolver.resolve(schema["$ref"]) 

260 validator.resolver.push_scope(scope) 

261 

262 try: 

263 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

264 validator, instance, resolved, 

265 ) 

266 finally: 

267 validator.resolver.pop_scope() 

268 

269 if "items" in schema: 

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

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

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

273 

274 if "if" in schema: 

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

276 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

278 ) 

279 if "then" in schema: 

280 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

282 ) 

283 else: 

284 if "else" in schema: 

285 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

287 ) 

288 

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

290 if keyword in schema: 

291 for k, v in enumerate(instance): 

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

293 evaluated_indexes.append(k) 

294 

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

296 if keyword in schema: 

297 for subschema in schema[keyword]: 

298 errs = list(validator.descend(instance, subschema)) 

299 if not errs: 

300 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

301 validator, instance, subschema, 

302 ) 

303 

304 return evaluated_indexes 

305 

306 

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

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

309 return 

310 evaluated_item_indexes = find_evaluated_item_indexes_by_schema( 

311 validator, instance, schema, 

312 ) 

313 unevaluated_items = [ 

314 item for index, item in enumerate(instance) 

315 if index not in evaluated_item_indexes 

316 ] 

317 if unevaluated_items: 

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

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