##// END OF EJS Templates
update Jsonschema version
Matthias BUSSONNIER -
Show More
@@ -0,0 +1,3 b''
1 _jsonschema from commit :
2 3ddd80543bd6da56eeea84b2f364febaeadf31b9
3
This diff has been collapsed as it changes many lines, (595 lines changed) Show them Hide them
@@ -1,12 +1,11 b''
1 1 """
2 2 An implementation of JSON Schema for Python
3 3
4 The main functionality is provided by the :class:`Validator` class, with the
5 :function:`validate` function being the most common way to quickly create a
6 :class:`Validator` object and validate an instance with a given schema.
4 The main functionality is provided by the validator classes for each of the
5 supported JSON Schema versions.
7 6
8 The :class:`Validator` class generally attempts to be as strict as possible
9 under the JSON Schema specification. See its docstring for details.
7 Most commonly, the :function:`validate` function is the quickest way to simply
8 validate a given instance under a schema, and will create a validator for you.
10 9
11 10 """
12 11
@@ -20,131 +19,33 b' import sys'
20 19 import warnings
21 20
22 21
22 __version__ = "0.7"
23
24 FLOAT_TOLERANCE = 10 ** -15
23 25 PY3 = sys.version_info[0] >= 3
24 26
25 27 if PY3:
26 28 basestring = unicode = str
27 29 iteritems = operator.methodcaller("items")
30 from urllib.parse import unquote
28 31 else:
29 32 from itertools import izip as zip
30 33 iteritems = operator.methodcaller("iteritems")
34 from urllib import unquote
31 35
32 36
33 def _uniq(container):
37 class UnknownType(Exception):
34 38 """
35 Check if all of a container's elements are unique.
36
37 Successively tries first to rely that the elements are hashable, then
38 falls back on them being sortable, and finally falls back on brute
39 force.
39 An unknown type was given.
40 40
41 41 """
42 42
43 try:
44 return len(set(container)) == len(container)
45 except TypeError:
46 try:
47 sort = sorted(container)
48 sliced = itertools.islice(container, 1, None)
49 for i, j in zip(container, sliced):
50 if i == j:
51 return False
52 except (NotImplementedError, TypeError):
53 seen = []
54 for e in container:
55 if e in seen:
56 return False
57 seen.append(e)
58 return True
59
60
61 __version__ = "0.5"
62
63
64 DRAFT_3 = {
65 "$schema" : "http://json-schema.org/draft-03/schema#",
66 "id" : "http://json-schema.org/draft-03/schema#",
67 "type" : "object",
68 43
69 "properties" : {
70 "type" : {
71 "type" : ["string", "array"],
72 "items" : {"type" : ["string", {"$ref" : "#"}]},
73 "uniqueItems" : True,
74 "default" : "any"
75 },
76 "properties" : {
77 "type" : "object",
78 "additionalProperties" : {"$ref" : "#", "type": "object"},
79 "default" : {}
80 },
81 "patternProperties" : {
82 "type" : "object",
83 "additionalProperties" : {"$ref" : "#"},
84 "default" : {}
85 },
86 "additionalProperties" : {
87 "type" : [{"$ref" : "#"}, "boolean"], "default" : {}
88 },
89 "items" : {
90 "type" : [{"$ref" : "#"}, "array"],
91 "items" : {"$ref" : "#"},
92 "default" : {}
93 },
94 "additionalItems" : {
95 "type" : [{"$ref" : "#"}, "boolean"], "default" : {}
96 },
97 "required" : {"type" : "boolean", "default" : False},
98 "dependencies" : {
99 "type" : ["string", "array", "object"],
100 "additionalProperties" : {
101 "type" : ["string", "array", {"$ref" : "#"}],
102 "items" : {"type" : "string"}
103 },
104 "default" : {}
105 },
106 "minimum" : {"type" : "number"},
107 "maximum" : {"type" : "number"},
108 "exclusiveMinimum" : {"type" : "boolean", "default" : False},
109 "exclusiveMaximum" : {"type" : "boolean", "default" : False},
110 "minItems" : {"type" : "integer", "minimum" : 0, "default" : 0},
111 "maxItems" : {"type" : "integer", "minimum" : 0},
112 "uniqueItems" : {"type" : "boolean", "default" : False},
113 "pattern" : {"type" : "string", "format" : "regex"},
114 "minLength" : {"type" : "integer", "minimum" : 0, "default" : 0},
115 "maxLength" : {"type" : "integer"},
116 "enum" : {"type" : "array", "minItems" : 1, "uniqueItems" : True},
117 "default" : {"type" : "any"},
118 "title" : {"type" : "string"},
119 "description" : {"type" : "string"},
120 "format" : {"type" : "string"},
121 "maxDecimal" : {"type" : "number", "minimum" : 0},
122 "divisibleBy" : {
123 "type" : "number",
124 "minimum" : 0,
125 "exclusiveMinimum" : True,
126 "default" : 1
127 },
128 "disallow" : {
129 "type" : ["string", "array"],
130 "items" : {"type" : ["string", {"$ref" : "#"}]},
131 "uniqueItems" : True
132 },
133 "extends" : {
134 "type" : [{"$ref" : "#"}, "array"],
135 "items" : {"$ref" : "#"},
136 "default" : {}
137 },
138 "id" : {"type" : "string", "format" : "uri"},
139 "$ref" : {"type" : "string", "format" : "uri"},
140 "$schema" : {"type" : "string", "format" : "uri"},
141 },
142 "dependencies" : {
143 "exclusiveMinimum" : "minimum", "exclusiveMaximum" : "maximum"
144 },
145 }
44 class InvalidRef(Exception):
45 """
46 An invalid reference was given.
146 47
147 EPSILON = 10 ** -15
48 """
148 49
149 50
150 51 class SchemaError(Exception):
@@ -188,9 +89,9 b' class ValidationError(Exception):'
188 89 self.path = []
189 90
190 91
191 class Validator(object):
92 class Draft3Validator(object):
192 93 """
193 A JSON Schema validator.
94 A validator for JSON Schema draft 3.
194 95
195 96 """
196 97
@@ -199,23 +100,12 b' class Validator(object):'
199 100 "number" : (int, float), "object" : dict, "string" : basestring,
200 101 }
201 102
202 def __init__(
203 self, version=DRAFT_3, unknown_type="skip",
204 unknown_property="skip", types=(),
205 ):
103 def __init__(self, schema, types=()):
206 104 """
207 Initialize a Validator.
208
209 ``version`` specifies which version of the JSON Schema specification to
210 validate with. Currently only draft-03 is supported (and is the
211 default).
105 Initialize a validator.
212 106
213 ``unknown_type`` and ``unknown_property`` control what to do when an
214 unknown type (resp. property) is encountered. By default, the
215 metaschema is respected (which e.g. for draft 3 allows a schema to have
216 additional properties), but if for some reason you want to modify this
217 behavior, you can do so without needing to modify the metaschema by
218 passing ``"error"`` or ``"warn"`` to these arguments.
107 ``schema`` should be a *valid* JSON Schema object already converted to
108 a native Python object (typically a dict via ``json.load``).
219 109
220 110 ``types`` is a mapping (or iterable of 2-tuples) containing additional
221 111 types or alternate types to verify via the 'type' property. For
@@ -223,100 +113,76 b' class Validator(object):'
223 113 ``int`` and ``float``. To override this behavior (e.g. for also
224 114 allowing ``decimal.Decimal``), pass ``types={"number" : (int, float,
225 115 decimal.Decimal)} *including* the default types if so desired, which
226 are fairly obvious but can be accessed via ``Validator.DEFAULT_TYPES``
227 if necessary.
116 are fairly obvious but can be accessed via the ``DEFAULT_TYPES``
117 attribute on this class if necessary.
228 118
229 119 """
230 120
231 self._unknown_type = unknown_type
232 self._unknown_property = unknown_property
233 self._version = version
234
235 121 self._types = dict(self.DEFAULT_TYPES)
236 122 self._types.update(types)
237 123 self._types["any"] = tuple(self._types.values())
238 124
125 self.schema = schema
126
239 127 def is_type(self, instance, type):
240 128 """
241 Check if an ``instance`` is of the provided ``type``.
129 Check if an ``instance`` is of the provided (JSON Schema) ``type``.
242 130
243 131 """
244 132
245 py_type = self._types.get(type)
246
247 if py_type is None:
248 return self.schema_error(
249 self._unknown_type, "%r is not a known type" % (type,)
250 )
133 if type not in self._types:
134 raise UnknownType(type)
135 type = self._types[type]
251 136
252 # the only thing we're careful about here is evading bool inheriting
253 # from int, so let's be even dirtier than usual
137 # bool inherits from int, so ensure bools aren't reported as integers
138 if isinstance(instance, bool):
139 type = _flatten(type)
140 if int in type and bool not in type:
141 return False
142 return isinstance(instance, type)
254 143
255 elif (
256 # it's not a bool, so no worries
257 not isinstance(instance, bool) or
144 def is_valid(self, instance, _schema=None):
145 """
146 Check if the ``instance`` is valid under the current schema.
258 147
259 # it is a bool, but we're checking for a bool, so no worries
260 (
261 py_type is bool or
262 isinstance(py_type, tuple) and bool in py_type
263 )
148 Returns a bool indicating whether validation succeeded.
264 149
265 ):
266 return isinstance(instance, py_type)
150 """
267 151
268 def schema_error(self, level, msg):
269 if level == "skip":
270 return
271 elif level == "warn":
272 warnings.warn(msg)
273 else:
274 raise SchemaError(msg)
152 error = next(self.iter_errors(instance, _schema), None)
153 return error is None
275 154
276 def is_valid(self, instance, schema, meta_validate=True):
155 @classmethod
156 def check_schema(cls, schema):
277 157 """
278 Check if the ``instance`` is valid under the ``schema``.
279
280 Returns a bool indicating whether validation succeeded.
158 Validate a ``schema`` against the meta-schema to see if it is valid.
281 159
282 160 """
283 161
284 error = next(self.iter_errors(instance, schema, meta_validate), None)
285 return error is None
162 for error in cls(cls.META_SCHEMA).iter_errors(schema):
163 s = SchemaError(error.message)
164 s.path = error.path
165 s.validator = error.validator
166 # I think we're safer raising these always, not yielding them
167 raise s
286 168
287 def iter_errors(self, instance, schema, meta_validate=True):
169 def iter_errors(self, instance, _schema=None):
288 170 """
289 171 Lazily yield each of the errors in the given ``instance``.
290 172
291 If you are unsure whether your schema itself is valid,
292 ``meta_validate`` will first validate that the schema is valid before
293 attempting to validate the instance. ``meta_validate`` is ``True`` by
294 default, since setting it to ``False`` can lead to confusing error
295 messages with an invalid schema. If you're sure your schema is in fact
296 valid, or don't care, feel free to set this to ``False``. The meta
297 validation will be done using the appropriate ``version``.
298
299 173 """
300 174
301 if meta_validate:
302 for error in self.iter_errors(
303 schema, self._version, meta_validate=False
304 ):
305 s = SchemaError(error.message)
306 s.path = error.path
307 s.validator = error.validator
308 # I think we're safer raising these always, not yielding them
309 raise s
310
311 for k, v in iteritems(schema):
175 if _schema is None:
176 _schema = self.schema
177
178 for k, v in iteritems(_schema):
312 179 validator = getattr(self, "validate_%s" % (k.lstrip("$"),), None)
313 180
314 181 if validator is None:
315 errors = self.unknown_property(k, instance, schema)
316 else:
317 errors = validator(v, instance, schema)
182 continue
318 183
319 for error in errors or ():
184 errors = validator(v, instance, _schema) or ()
185 for error in errors:
320 186 # if the validator hasn't already been set (due to recursion)
321 187 # make sure to set it
322 188 error.validator = error.validator or k
@@ -331,12 +197,6 b' class Validator(object):'
331 197 for error in self.iter_errors(*args, **kwargs):
332 198 raise error
333 199
334 def unknown_property(self, property, instance, schema):
335 self.schema_error(
336 self._unknown_property,
337 "%r is not a known schema property" % (property,)
338 )
339
340 200 def validate_type(self, types, instance, schema):
341 201 types = _list(types)
342 202
@@ -357,9 +217,7 b' class Validator(object):'
357 217 )):
358 218 return
359 219 else:
360 yield ValidationError(
361 "%r is not of type %r" % (instance, _delist(types))
362 )
220 yield ValidationError(_types_msg(instance, types))
363 221
364 222 def validate_properties(self, properties, instance, schema):
365 223 if not self.is_type(instance, "object"):
@@ -367,22 +225,7 b' class Validator(object):'
367 225
368 226 for property, subschema in iteritems(properties):
369 227 if property in instance:
370 dependencies = _list(subschema.get("dependencies", []))
371 if self.is_type(dependencies, "object"):
372 for error in self.iter_errors(
373 instance, dependencies, meta_validate=False
374 ):
375 yield error
376 else:
377 for dependency in dependencies:
378 if dependency not in instance:
379 yield ValidationError(
380 "%r is a dependency of %r" % (dependency, property)
381 )
382
383 for error in self.iter_errors(
384 instance[property], subschema, meta_validate=False
385 ):
228 for error in self.iter_errors(instance[property], subschema):
386 229 error.path.append(property)
387 230 yield error
388 231 elif subschema.get("required", False):
@@ -397,59 +240,71 b' class Validator(object):'
397 240 for pattern, subschema in iteritems(patternProperties):
398 241 for k, v in iteritems(instance):
399 242 if re.match(pattern, k):
400 for error in self.iter_errors(
401 v, subschema, meta_validate=False
402 ):
243 for error in self.iter_errors(v, subschema):
403 244 yield error
404 245
405 246 def validate_additionalProperties(self, aP, instance, schema):
406 247 if not self.is_type(instance, "object"):
407 248 return
408 249
409 # no viewkeys in <2.7, and pypy seems to fail on vk - vk anyhow, so...
410 extras = set(instance) - set(schema.get("properties", {}))
250 extras = set(_find_additional_properties(instance, schema))
411 251
412 252 if self.is_type(aP, "object"):
413 253 for extra in extras:
414 for error in self.iter_errors(
415 instance[extra], aP, meta_validate=False
416 ):
254 for error in self.iter_errors(instance[extra], aP):
417 255 yield error
418 256 elif not aP and extras:
419 257 error = "Additional properties are not allowed (%s %s unexpected)"
420 258 yield ValidationError(error % _extras_msg(extras))
421 259
260 def validate_dependencies(self, dependencies, instance, schema):
261 if not self.is_type(instance, "object"):
262 return
263
264 for property, dependency in iteritems(dependencies):
265 if property not in instance:
266 continue
267
268 if self.is_type(dependency, "object"):
269 for error in self.iter_errors(instance, dependency):
270 yield error
271 else:
272 dependencies = _list(dependency)
273 for dependency in dependencies:
274 if dependency not in instance:
275 yield ValidationError(
276 "%r is a dependency of %r" % (dependency, property)
277 )
278
422 279 def validate_items(self, items, instance, schema):
423 280 if not self.is_type(instance, "array"):
424 281 return
425 282
426 283 if self.is_type(items, "object"):
427 284 for index, item in enumerate(instance):
428 for error in self.iter_errors(
429 item, items, meta_validate=False
430 ):
285 for error in self.iter_errors(item, items):
431 286 error.path.append(index)
432 287 yield error
433 288 else:
434 289 for (index, item), subschema in zip(enumerate(instance), items):
435 for error in self.iter_errors(
436 item, subschema, meta_validate=False
437 ):
290 for error in self.iter_errors(item, subschema):
438 291 error.path.append(index)
439 292 yield error
440 293
441 294 def validate_additionalItems(self, aI, instance, schema):
442 295 if not self.is_type(instance, "array"):
443 296 return
297 if not self.is_type(schema.get("items"), "array"):
298 return
444 299
445 300 if self.is_type(aI, "object"):
446 301 for item in instance[len(schema):]:
447 for error in self.iter_errors(item, aI, meta_validate=False):
302 for error in self.iter_errors(item, aI):
448 303 yield error
449 304 elif not aI and len(instance) > len(schema.get("items", [])):
450 305 error = "Additional items are not allowed (%s %s unexpected)"
451 306 yield ValidationError(
452 error % _extras_msg(instance[len(schema) - 1:])
307 error % _extras_msg(instance[len(schema.get("items", [])):])
453 308 )
454 309
455 310 def validate_minimum(self, minimum, instance, schema):
@@ -520,7 +375,7 b' class Validator(object):'
520 375
521 376 if isinstance(dB, float):
522 377 mod = instance % dB
523 failed = (mod > EPSILON) and (dB - mod) > EPSILON
378 failed = (mod > FLOAT_TOLERANCE) and (dB - mod) > FLOAT_TOLERANCE
524 379 else:
525 380 failed = instance % dB
526 381
@@ -538,20 +393,119 b' class Validator(object):'
538 393 if self.is_type(extends, "object"):
539 394 extends = [extends]
540 395 for subschema in extends:
541 for error in self.iter_errors(
542 instance, subschema, meta_validate=False
543 ):
396 for error in self.iter_errors(instance, subschema):
544 397 yield error
545 398
399 def validate_ref(self, ref, instance, schema):
400 if ref != "#" and not ref.startswith("#/"):
401 warnings.warn("jsonschema only supports json-pointer $refs")
402 return
403
404 resolved = resolve_json_pointer(self.schema, ref)
405 for error in self.iter_errors(instance, resolved):
406 yield error
407
408
409 Draft3Validator.META_SCHEMA = {
410 "$schema" : "http://json-schema.org/draft-03/schema#",
411 "id" : "http://json-schema.org/draft-03/schema#",
412 "type" : "object",
413
414 "properties" : {
415 "type" : {
416 "type" : ["string", "array"],
417 "items" : {"type" : ["string", {"$ref" : "#"}]},
418 "uniqueItems" : True,
419 "default" : "any"
420 },
421 "properties" : {
422 "type" : "object",
423 "additionalProperties" : {"$ref" : "#", "type": "object"},
424 "default" : {}
425 },
426 "patternProperties" : {
427 "type" : "object",
428 "additionalProperties" : {"$ref" : "#"},
429 "default" : {}
430 },
431 "additionalProperties" : {
432 "type" : [{"$ref" : "#"}, "boolean"], "default" : {}
433 },
434 "items" : {
435 "type" : [{"$ref" : "#"}, "array"],
436 "items" : {"$ref" : "#"},
437 "default" : {}
438 },
439 "additionalItems" : {
440 "type" : [{"$ref" : "#"}, "boolean"], "default" : {}
441 },
442 "required" : {"type" : "boolean", "default" : False},
443 "dependencies" : {
444 "type" : ["string", "array", "object"],
445 "additionalProperties" : {
446 "type" : ["string", "array", {"$ref" : "#"}],
447 "items" : {"type" : "string"}
448 },
449 "default" : {}
450 },
451 "minimum" : {"type" : "number"},
452 "maximum" : {"type" : "number"},
453 "exclusiveMinimum" : {"type" : "boolean", "default" : False},
454 "exclusiveMaximum" : {"type" : "boolean", "default" : False},
455 "minItems" : {"type" : "integer", "minimum" : 0, "default" : 0},
456 "maxItems" : {"type" : "integer", "minimum" : 0},
457 "uniqueItems" : {"type" : "boolean", "default" : False},
458 "pattern" : {"type" : "string", "format" : "regex"},
459 "minLength" : {"type" : "integer", "minimum" : 0, "default" : 0},
460 "maxLength" : {"type" : "integer"},
461 "enum" : {"type" : "array", "minItems" : 1, "uniqueItems" : True},
462 "default" : {"type" : "any"},
463 "title" : {"type" : "string"},
464 "description" : {"type" : "string"},
465 "format" : {"type" : "string"},
466 "maxDecimal" : {"type" : "number", "minimum" : 0},
467 "divisibleBy" : {
468 "type" : "number",
469 "minimum" : 0,
470 "exclusiveMinimum" : True,
471 "default" : 1
472 },
473 "disallow" : {
474 "type" : ["string", "array"],
475 "items" : {"type" : ["string", {"$ref" : "#"}]},
476 "uniqueItems" : True
477 },
478 "extends" : {
479 "type" : [{"$ref" : "#"}, "array"],
480 "items" : {"$ref" : "#"},
481 "default" : {}
482 },
483 "id" : {"type" : "string", "format" : "uri"},
484 "$ref" : {"type" : "string", "format" : "uri"},
485 "$schema" : {"type" : "string", "format" : "uri"},
486 },
487 "dependencies" : {
488 "exclusiveMinimum" : "minimum", "exclusiveMaximum" : "maximum"
489 },
490 }
491
546 492
547 for no_op in [ # handled in:
548 "dependencies", "required", # properties
549 "exclusiveMinimum", "exclusiveMaximum", # min*/max*
550 "default", "description", "format", "id", # no validation needed
551 "links", "name", "title",
552 "ref", "schema", # not yet supported
553 ]:
554 setattr(Validator, "validate_" + no_op, lambda *args, **kwargs : None)
493 class Validator(Draft3Validator):
494 """
495 Deprecated: Use :class:`Draft3Validator` instead.
496
497 """
498
499 def __init__(
500 self, version=None, unknown_type="skip", unknown_property="skip",
501 *args, **kwargs
502 ):
503 super(Validator, self).__init__({}, *args, **kwargs)
504 warnings.warn(
505 "Validator is deprecated and will be removed. "
506 "Use Draft3Validator instead.",
507 DeprecationWarning, stacklevel=2,
508 )
555 509
556 510
557 511 class ErrorTree(object):
@@ -590,6 +544,51 b' class ErrorTree(object):'
590 544 return "<%s (%s errors)>" % (self.__class__.__name__, len(self))
591 545
592 546
547 def resolve_json_pointer(schema, ref):
548 """
549 Resolve a local reference ``ref`` within the given root ``schema``.
550
551 ``ref`` should be a local ref whose ``#`` is still present.
552
553 """
554
555 if ref == "#":
556 return schema
557
558 parts = ref.lstrip("#/").split("/")
559
560 parts = map(unquote, parts)
561 parts = [part.replace('~1', '/').replace('~0', '~') for part in parts]
562
563 try:
564 for part in parts:
565 schema = schema[part]
566 except KeyError:
567 raise InvalidRef("Unresolvable json-pointer %r" % ref)
568 else:
569 return schema
570
571
572 def _find_additional_properties(instance, schema):
573 """
574 Return the set of additional properties for the given ``instance``.
575
576 Weeds out properties that should have been validated by ``properties`` and
577 / or ``patternProperties``.
578
579 Assumes ``instance`` is dict-like already.
580
581 """
582
583 properties = schema.get("properties", {})
584 patterns = "|".join(schema.get("patternProperties", {}))
585 for property in instance:
586 if property not in properties:
587 if patterns and re.search(patterns, property):
588 continue
589 yield property
590
591
593 592 def _extras_msg(extras):
594 593 """
595 594 Create an error message for extra items or properties.
@@ -603,6 +602,49 b' def _extras_msg(extras):'
603 602 return ", ".join(repr(extra) for extra in extras), verb
604 603
605 604
605 def _types_msg(instance, types):
606 """
607 Create an error message for a failure to match the given types.
608
609 If the ``instance`` is an object and contains a ``name`` property, it will
610 be considered to be a description of that object and used as its type.
611
612 Otherwise the message is simply the reprs of the given ``types``.
613
614 """
615
616 reprs = []
617 for type in types:
618 try:
619 reprs.append(repr(type["name"]))
620 except Exception:
621 reprs.append(repr(type))
622 return "%r is not of type %s" % (instance, ", ".join(reprs))
623
624
625 def _flatten(suitable_for_isinstance):
626 """
627 isinstance() can accept a bunch of really annoying different types:
628 * a single type
629 * a tuple of types
630 * an arbitrary nested tree of tuples
631
632 Return a flattened tuple of the given argument.
633
634 """
635
636 types = set()
637
638 if not isinstance(suitable_for_isinstance, tuple):
639 suitable_for_isinstance = (suitable_for_isinstance,)
640 for thing in suitable_for_isinstance:
641 if isinstance(thing, tuple):
642 types.update(_flatten(thing))
643 else:
644 types.add(thing)
645 return tuple(types)
646
647
606 648 def _list(thing):
607 649 """
608 650 Wrap ``thing`` in a list if it's a single str.
@@ -633,21 +675,60 b' def _delist(thing):'
633 675 return thing
634 676
635 677
636 def validate(
637 instance, schema, meta_validate=True, cls=Validator, *args, **kwargs
638 ):
678 def _uniq(container):
679 """
680 Check if all of a container's elements are unique.
681
682 Successively tries first to rely that the elements are hashable, then
683 falls back on them being sortable, and finally falls back on brute
684 force.
685
686 """
687
688 try:
689 return len(set(container)) == len(container)
690 except TypeError:
691 try:
692 sort = sorted(container)
693 sliced = itertools.islice(container, 1, None)
694 for i, j in zip(container, sliced):
695 if i == j:
696 return False
697 except (NotImplementedError, TypeError):
698 seen = []
699 for e in container:
700 if e in seen:
701 return False
702 seen.append(e)
703 return True
704
705
706 def validate(instance, schema, cls=Draft3Validator, *args, **kwargs):
639 707 """
640 708 Validate an ``instance`` under the given ``schema``.
641 709
642 By default, the :class:`Validator` class from this module is used to
643 perform the validation. To use another validator, pass it into the ``cls``
644 argument.
710 First verifies that the provided schema is itself valid, since not doing so
711 can lead to less obvious failures when validating. If you know it is or
712 don't care, use ``YourValidator(schema).validate(instance)`` directly
713 instead (e.g. ``Draft3Validator``).
645 714
646 Any other provided positional and keyword arguments will be provided to the
647 ``cls``. See the :class:`Validator` class' docstring for details on the
648 arguments it accepts.
715 ``cls`` is a validator class that will be used to validate the instance.
716 By default this is a draft 3 validator. Any other provided positional and
717 keyword arguments will be provided to this class when constructing a
718 validator.
649 719
650 720 """
651 721
652 validator = cls(*args, **kwargs)
653 validator.validate(instance, schema, meta_validate=meta_validate)
722
723 meta_validate = kwargs.pop("meta_validate", None)
724
725 if meta_validate is not None:
726 warnings.warn(
727 "meta_validate is deprecated and will be removed. If you do not "
728 "want to validate a schema, use Draft3Validator.validate instead.",
729 DeprecationWarning, stacklevel=2,
730 )
731
732 if meta_validate is not False: # yes this is needed since True was default
733 cls.check_schema(schema)
734 cls(schema, *args, **kwargs).validate(instance)
@@ -1,19 +1,19 b''
1 1 #!/usr/bin/env python
2 2 # -*- coding: utf8 -*-
3 3
4 from IPython.external.jsonschema import Validator, validate, ValidationError
4 from IPython.external.jsonschema import Draft3Validator, validate, ValidationError
5 5 import IPython.external.jsonpointer as jsonpointer
6 6 import argparse
7 7 import traceback
8 8 import json
9 9
10 v = Validator();
11 10 def nbvalidate(nbjson, schema='v3.withref.json', key=None,verbose=True):
12 11 v3schema = resolve_ref(json.load(open(schema,'r')))
13 12 if key :
14 13 v3schema = jsonpointer.resolve_pointer(v3schema,key)
15 14 errors = 0
16 for error in v.iter_errors(nbjson, v3schema):
15 v = Draft3Validator(v3schema);
16 for error in v.iter_errors(nbjson):
17 17 errors = errors + 1
18 18 if verbose:
19 19 print(error)
General Comments 0
You need to be logged in to leave comments. Login now