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

163 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:30 +0000

1from referencing.jsonschema import lookup_recursive_ref 

2 

3from jsonschema import _utils 

4from jsonschema.exceptions import ValidationError 

5 

6 

7def ignore_ref_siblings(schema): 

8 """ 

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

10 

11 Otherwise, return all keywords. 

12 

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

14 """ 

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

16 if ref is not None: 

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

18 else: 

19 return schema.items() 

20 

21 

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

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

24 return 

25 

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

27 if property not in instance: 

28 continue 

29 

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

31 yield from validator.descend( 

32 instance, dependency, schema_path=property, 

33 ) 

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

35 if dependency not in instance: 

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

37 yield ValidationError(message) 

38 else: 

39 for each in dependency: 

40 if each not in instance: 

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

42 yield ValidationError(message) 

43 

44 

45def dependencies_draft4_draft6_draft7( 

46 validator, 

47 dependencies, 

48 instance, 

49 schema, 

50): 

51 """ 

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

53 

54 In later drafts, the keyword was split into separate 

55 ``dependentRequired`` and ``dependentSchemas`` validators. 

56 """ 

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

58 return 

59 

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

61 if property not in instance: 

62 continue 

63 

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

65 for each in dependency: 

66 if each not in instance: 

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

68 yield ValidationError(message) 

69 else: 

70 yield from validator.descend( 

71 instance, dependency, schema_path=property, 

72 ) 

73 

74 

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

76 for disallowed in _utils.ensure_list(disallow): 

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

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

79 yield ValidationError(message) 

80 

81 

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

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

84 yield from validator.descend(instance, extends) 

85 return 

86 for index, subschema in enumerate(extends): 

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

88 

89 

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

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

92 return 

93 

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

95 for index, item in enumerate(instance): 

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

97 else: 

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

99 yield from validator.descend( 

100 item, subschema, path=index, schema_path=index, 

101 ) 

102 

103 

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

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

106 return 

107 

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

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

114 for index, item in enumerate(instance): 

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

116 

117 

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

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

120 return 

121 

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

123 failed = instance <= minimum 

124 cmp = "less than or equal to" 

125 else: 

126 failed = instance < minimum 

127 cmp = "less than" 

128 

129 if failed: 

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

131 yield ValidationError(message) 

132 

133 

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

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

136 return 

137 

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

139 failed = instance >= maximum 

140 cmp = "greater than or equal to" 

141 else: 

142 failed = instance > maximum 

143 cmp = "greater than" 

144 

145 if failed: 

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

147 yield ValidationError(message) 

148 

149 

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

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

152 return 

153 

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

155 if property in instance: 

156 yield from validator.descend( 

157 instance[property], 

158 subschema, 

159 path=property, 

160 schema_path=property, 

161 ) 

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

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

164 error._set( 

165 validator="required", 

166 validator_value=subschema["required"], 

167 instance=instance, 

168 schema=schema, 

169 ) 

170 error.path.appendleft(property) 

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

172 yield error 

173 

174 

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

176 types = _utils.ensure_list(types) 

177 

178 all_errors = [] 

179 for index, type in enumerate(types): 

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

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

182 if not errors: 

183 return 

184 all_errors.extend(errors) 

185 else: 

186 if validator.is_type(instance, type): 

187 return 

188 else: 

189 reprs = [] 

190 for type in types: 

191 try: 

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

193 except Exception: 

194 reprs.append(repr(type)) 

195 yield ValidationError( 

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

197 context=all_errors, 

198 ) 

199 

200 

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

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

203 return 

204 

205 if not any( 

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

207 for element in instance 

208 ): 

209 yield ValidationError( 

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

211 ) 

212 

213 

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

215 resolved = lookup_recursive_ref(validator._resolver) 

216 yield from validator.descend( 

217 instance, 

218 resolved.contents, 

219 resolver=resolved.resolver, 

220 ) 

221 

222 

223def find_evaluated_item_indexes_by_schema(validator, instance, schema): 

224 """ 

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

226 

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

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

229 """ 

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

231 return [] 

232 evaluated_indexes = [] 

233 

234 if "$ref" in schema: 

235 resolved = validator._resolver.lookup(schema["$ref"]) 

236 evaluated_indexes.extend( 

237 find_evaluated_item_indexes_by_schema( 

238 validator.evolve( 

239 schema=resolved.contents, 

240 _resolver=resolved.resolver, 

241 ), 

242 instance, 

243 resolved.contents, 

244 ), 

245 ) 

246 

247 if "items" in schema: 

248 if "additionalItems" in schema: 

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

250 

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

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

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

254 

255 if "if" in schema: 

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

257 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

259 ) 

260 if "then" in schema: 

261 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

263 ) 

264 else: 

265 if "else" in schema: 

266 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

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

268 ) 

269 

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

271 if keyword in schema: 

272 for k, v in enumerate(instance): 

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

274 evaluated_indexes.append(k) 

275 

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

277 if keyword in schema: 

278 for subschema in schema[keyword]: 

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

280 if errs is None: 

281 evaluated_indexes += find_evaluated_item_indexes_by_schema( 

282 validator, instance, subschema, 

283 ) 

284 

285 return evaluated_indexes 

286 

287 

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

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

290 return 

291 evaluated_item_indexes = find_evaluated_item_indexes_by_schema( 

292 validator, instance, schema, 

293 ) 

294 unevaluated_items = [ 

295 item for index, item in enumerate(instance) 

296 if index not in evaluated_item_indexes 

297 ] 

298 if unevaluated_items: 

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

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