1import re 2 3from jsonschema._utils import ( 4 ensure_list, 5 equal, 6 extras_msg, 7 find_additional_properties, 8 types_msg, 9 unbool, 10 uniq, 11) 12from jsonschema.exceptions import FormatError, ValidationError 13from jsonschema.compat import iteritems 14 15 16def patternProperties(validator, patternProperties, instance, schema): 17 if not validator.is_type(instance, "object"): 18 return 19 20 for pattern, subschema in iteritems(patternProperties): 21 for k, v in iteritems(instance): 22 if re.search(pattern, k): 23 for error in validator.descend( 24 v, subschema, path=k, schema_path=pattern, 25 ): 26 yield error 27 28 29def propertyNames(validator, propertyNames, instance, schema): 30 if not validator.is_type(instance, "object"): 31 return 32 33 for property in instance: 34 for error in validator.descend( 35 instance=property, 36 schema=propertyNames, 37 ): 38 yield error 39 40 41def additionalProperties(validator, aP, instance, schema): 42 if not validator.is_type(instance, "object"): 43 return 44 45 extras = set(find_additional_properties(instance, schema)) 46 47 if validator.is_type(aP, "object"): 48 for extra in extras: 49 for error in validator.descend(instance[extra], aP, path=extra): 50 yield error 51 elif not aP and extras: 52 if "patternProperties" in schema: 53 patterns = sorted(schema["patternProperties"]) 54 if len(extras) == 1: 55 verb = "does" 56 else: 57 verb = "do" 58 error = "%s %s not match any of the regexes: %s" % ( 59 ", ".join(map(repr, sorted(extras))), 60 verb, 61 ", ".join(map(repr, patterns)), 62 ) 63 yield ValidationError(error) 64 else: 65 error = "Additional properties are not allowed (%s %s unexpected)" 66 yield ValidationError(error % extras_msg(extras)) 67 68 69def items(validator, items, instance, schema): 70 if not validator.is_type(instance, "array"): 71 return 72 73 if validator.is_type(items, "array"): 74 for (index, item), subschema in zip(enumerate(instance), items): 75 for error in validator.descend( 76 item, subschema, path=index, schema_path=index, 77 ): 78 yield error 79 else: 80 for index, item in enumerate(instance): 81 for error in validator.descend(item, items, path=index): 82 yield error 83 84 85def additionalItems(validator, aI, instance, schema): 86 if ( 87 not validator.is_type(instance, "array") or 88 validator.is_type(schema.get("items", {}), "object") 89 ): 90 return 91 92 len_items = len(schema.get("items", [])) 93 if validator.is_type(aI, "object"): 94 for index, item in enumerate(instance[len_items:], start=len_items): 95 for error in validator.descend(item, aI, path=index): 96 yield error 97 elif not aI and len(instance) > len(schema.get("items", [])): 98 error = "Additional items are not allowed (%s %s unexpected)" 99 yield ValidationError( 100 error % 101 extras_msg(instance[len(schema.get("items", [])):]) 102 ) 103 104 105def const(validator, const, instance, schema): 106 if not equal(instance, const): 107 yield ValidationError("%r was expected" % (const,)) 108 109 110def contains(validator, contains, instance, schema): 111 if not validator.is_type(instance, "array"): 112 return 113 114 if not any(validator.is_valid(element, contains) for element in instance): 115 yield ValidationError( 116 "None of %r are valid under the given schema" % (instance,) 117 ) 118 119 120def exclusiveMinimum(validator, minimum, instance, schema): 121 if not validator.is_type(instance, "number"): 122 return 123 124 if instance <= minimum: 125 yield ValidationError( 126 "%r is less than or equal to the minimum of %r" % ( 127 instance, minimum, 128 ), 129 ) 130 131 132def exclusiveMaximum(validator, maximum, instance, schema): 133 if not validator.is_type(instance, "number"): 134 return 135 136 if instance >= maximum: 137 yield ValidationError( 138 "%r is greater than or equal to the maximum of %r" % ( 139 instance, maximum, 140 ), 141 ) 142 143 144def minimum(validator, minimum, instance, schema): 145 if not validator.is_type(instance, "number"): 146 return 147 148 if instance < minimum: 149 yield ValidationError( 150 "%r is less than the minimum of %r" % (instance, minimum) 151 ) 152 153 154def maximum(validator, maximum, instance, schema): 155 if not validator.is_type(instance, "number"): 156 return 157 158 if instance > maximum: 159 yield ValidationError( 160 "%r is greater than the maximum of %r" % (instance, maximum) 161 ) 162 163 164def multipleOf(validator, dB, instance, schema): 165 if not validator.is_type(instance, "number"): 166 return 167 168 if isinstance(dB, float): 169 quotient = instance / dB 170 failed = int(quotient) != quotient 171 else: 172 failed = instance % dB 173 174 if failed: 175 yield ValidationError("%r is not a multiple of %r" % (instance, dB)) 176 177 178def minItems(validator, mI, instance, schema): 179 if validator.is_type(instance, "array") and len(instance) < mI: 180 yield ValidationError("%r is too short" % (instance,)) 181 182 183def maxItems(validator, mI, instance, schema): 184 if validator.is_type(instance, "array") and len(instance) > mI: 185 yield ValidationError("%r is too long" % (instance,)) 186 187 188def uniqueItems(validator, uI, instance, schema): 189 if ( 190 uI and 191 validator.is_type(instance, "array") and 192 not uniq(instance) 193 ): 194 yield ValidationError("%r has non-unique elements" % (instance,)) 195 196 197def pattern(validator, patrn, instance, schema): 198 if ( 199 validator.is_type(instance, "string") and 200 not re.search(patrn, instance) 201 ): 202 yield ValidationError("%r does not match %r" % (instance, patrn)) 203 204 205def format(validator, format, instance, schema): 206 if validator.format_checker is not None: 207 try: 208 validator.format_checker.check(instance, format) 209 except FormatError as error: 210 yield ValidationError(error.message, cause=error.cause) 211 212 213def minLength(validator, mL, instance, schema): 214 if validator.is_type(instance, "string") and len(instance) < mL: 215 yield ValidationError("%r is too short" % (instance,)) 216 217 218def maxLength(validator, mL, instance, schema): 219 if validator.is_type(instance, "string") and len(instance) > mL: 220 yield ValidationError("%r is too long" % (instance,)) 221 222 223def dependencies(validator, dependencies, instance, schema): 224 if not validator.is_type(instance, "object"): 225 return 226 227 for property, dependency in iteritems(dependencies): 228 if property not in instance: 229 continue 230 231 if validator.is_type(dependency, "array"): 232 for each in dependency: 233 if each not in instance: 234 message = "%r is a dependency of %r" 235 yield ValidationError(message % (each, property)) 236 else: 237 for error in validator.descend( 238 instance, dependency, schema_path=property, 239 ): 240 yield error 241 242 243def enum(validator, enums, instance, schema): 244 if instance == 0 or instance == 1: 245 unbooled = unbool(instance) 246 if all(unbooled != unbool(each) for each in enums): 247 yield ValidationError("%r is not one of %r" % (instance, enums)) 248 elif instance not in enums: 249 yield ValidationError("%r is not one of %r" % (instance, enums)) 250 251 252def ref(validator, ref, instance, schema): 253 resolve = getattr(validator.resolver, "resolve", None) 254 if resolve is None: 255 with validator.resolver.resolving(ref) as resolved: 256 for error in validator.descend(instance, resolved): 257 yield error 258 else: 259 scope, resolved = validator.resolver.resolve(ref) 260 validator.resolver.push_scope(scope) 261 262 try: 263 for error in validator.descend(instance, resolved): 264 yield error 265 finally: 266 validator.resolver.pop_scope() 267 268 269def type(validator, types, instance, schema): 270 types = ensure_list(types) 271 272 if not any(validator.is_type(instance, type) for type in types): 273 yield ValidationError(types_msg(instance, types)) 274 275 276def properties(validator, properties, instance, schema): 277 if not validator.is_type(instance, "object"): 278 return 279 280 for property, subschema in iteritems(properties): 281 if property in instance: 282 for error in validator.descend( 283 instance[property], 284 subschema, 285 path=property, 286 schema_path=property, 287 ): 288 yield error 289 290 291def required(validator, required, instance, schema): 292 if not validator.is_type(instance, "object"): 293 return 294 for property in required: 295 if property not in instance: 296 yield ValidationError("%r is a required property" % property) 297 298 299def minProperties(validator, mP, instance, schema): 300 if validator.is_type(instance, "object") and len(instance) < mP: 301 yield ValidationError( 302 "%r does not have enough properties" % (instance,) 303 ) 304 305 306def maxProperties(validator, mP, instance, schema): 307 if not validator.is_type(instance, "object"): 308 return 309 if validator.is_type(instance, "object") and len(instance) > mP: 310 yield ValidationError("%r has too many properties" % (instance,)) 311 312 313def allOf(validator, allOf, instance, schema): 314 for index, subschema in enumerate(allOf): 315 for error in validator.descend(instance, subschema, schema_path=index): 316 yield error 317 318 319def anyOf(validator, anyOf, instance, schema): 320 all_errors = [] 321 for index, subschema in enumerate(anyOf): 322 errs = list(validator.descend(instance, subschema, schema_path=index)) 323 if not errs: 324 break 325 all_errors.extend(errs) 326 else: 327 yield ValidationError( 328 "%r is not valid under any of the given schemas" % (instance,), 329 context=all_errors, 330 ) 331 332 333def oneOf(validator, oneOf, instance, schema): 334 subschemas = enumerate(oneOf) 335 all_errors = [] 336 for index, subschema in subschemas: 337 errs = list(validator.descend(instance, subschema, schema_path=index)) 338 if not errs: 339 first_valid = subschema 340 break 341 all_errors.extend(errs) 342 else: 343 yield ValidationError( 344 "%r is not valid under any of the given schemas" % (instance,), 345 context=all_errors, 346 ) 347 348 more_valid = [s for i, s in subschemas if validator.is_valid(instance, s)] 349 if more_valid: 350 more_valid.append(first_valid) 351 reprs = ", ".join(repr(schema) for schema in more_valid) 352 yield ValidationError( 353 "%r is valid under each of %s" % (instance, reprs) 354 ) 355 356 357def not_(validator, not_schema, instance, schema): 358 if validator.is_valid(instance, not_schema): 359 yield ValidationError( 360 "%r is not allowed for %r" % (not_schema, instance) 361 ) 362 363 364def if_(validator, if_schema, instance, schema): 365 if validator.is_valid(instance, if_schema): 366 if u"then" in schema: 367 then = schema[u"then"] 368 for error in validator.descend(instance, then, schema_path="then"): 369 yield error 370 elif u"else" in schema: 371 else_ = schema[u"else"] 372 for error in validator.descend(instance, else_, schema_path="else"): 373 yield error 374