validator.py
99 lines
| 2.8 KiB
| text/x-python
|
PythonLexer
Thomas Kluyver
|
r13348 | from __future__ import print_function | ||
Matthias BUSSONNIER
|
r8519 | #!/usr/bin/env python | ||
# -*- coding: utf8 -*- | ||||
Thomas Kluyver
|
r12547 | import json | ||
Jessica B. Hamrick
|
r16330 | import os | ||
Matthias BUSSONNIER
|
r8519 | |||
Jessica B. Hamrick
|
r16347 | from IPython.external.jsonschema import Draft3Validator, SchemaError | ||
Matthias BUSSONNIER
|
r8525 | import IPython.external.jsonpointer as jsonpointer | ||
Thomas Kluyver
|
r13361 | from IPython.utils.py3compat import iteritems | ||
Matthias BUSSONNIER
|
r8519 | |||
Jessica B. Hamrick
|
r16330 | |||
from .current import nbformat, nbformat_schema | ||||
Jessica B. Hamrick
|
r16335 | schema_path = os.path.join( | ||
Jessica B. Hamrick
|
r16330 | os.path.split(__file__)[0], "v%d" % nbformat, nbformat_schema) | ||
Jessica B. Hamrick
|
r16347 | def isvalid(nbjson, verbose=False): | ||
"""Checks whether the given notebook JSON conforms to the current | ||||
notebook format schema. Returns True if the JSON is valid, and | ||||
False otherwise. | ||||
If `verbose` is set, then print out each error that is detected. | ||||
""" | ||||
errors = validate(nbjson, verbose=verbose) | ||||
Jessica B. Hamrick
|
r16341 | return errors == 0 | ||
Jessica B. Hamrick
|
r16347 | def validate(nbjson, verbose=False): | ||
"""Checks whether the given notebook JSON conforms to the current | ||||
notebook format schema, and returns the number of errors. | ||||
If `verbose` is set, then print out each error that is detected. | ||||
""" | ||||
Jessica B. Hamrick
|
r16335 | # load the schema file | ||
with open(schema_path, 'r') as fh: | ||||
schema_json = json.load(fh) | ||||
# resolve internal references | ||||
v3schema = resolve_ref(schema_json) | ||||
Jessica B. Hamrick
|
r16347 | v3schema = jsonpointer.resolve_pointer(v3schema, '/notebook') | ||
Jessica B. Hamrick
|
r16335 | |||
Jessica B. Hamrick
|
r16347 | # count how many errors there are | ||
Matthias BUSSONNIER
|
r8519 | errors = 0 | ||
Jessica B. Hamrick
|
r16330 | v = Draft3Validator(v3schema) | ||
Matthias BUSSONNIER
|
r8674 | for error in v.iter_errors(nbjson): | ||
Matthias BUSSONNIER
|
r8519 | errors = errors + 1 | ||
if verbose: | ||||
print(error) | ||||
Jessica B. Hamrick
|
r16335 | |||
Matthias BUSSONNIER
|
r8519 | return errors | ||
Jessica B. Hamrick
|
r16330 | |||
Jessica B. Hamrick
|
r16335 | def resolve_ref(json, schema=None): | ||
Jessica B. Hamrick
|
r16347 | """Resolve internal references within the given JSON. This essentially | ||
means that dictionaries of this form: | ||||
{"$ref": "/somepointer"} | ||||
will be replaced with the resolved reference to `/somepointer`. | ||||
This only supports local reference to the same JSON file. | ||||
Matthias BUSSONNIER
|
r8519 | |||
""" | ||||
Jessica B. Hamrick
|
r16335 | if not schema: | ||
schema = json | ||||
# if it's a list, resolve references for each item in the list | ||||
Matthias BUSSONNIER
|
r8519 | if type(json) is list: | ||
Jessica B. Hamrick
|
r16335 | resolved = [] | ||
Matthias BUSSONNIER
|
r8519 | for item in json: | ||
Jessica B. Hamrick
|
r16335 | resolved.append(resolve_ref(item, schema=schema)) | ||
# if it's a dictionary, resolve references for each item in the | ||||
# dictionary | ||||
Matthias BUSSONNIER
|
r8519 | elif type(json) is dict: | ||
Jessica B. Hamrick
|
r16335 | resolved = {} | ||
for key, ref in iteritems(json): | ||||
Jessica B. Hamrick
|
r16347 | |||
Jessica B. Hamrick
|
r16335 | # if the key is equal to $ref, then replace the entire | ||
# dictionary with the resolved value | ||||
Matthias BUSSONNIER
|
r8519 | if key == '$ref': | ||
Jessica B. Hamrick
|
r16347 | if len(json) != 1: | ||
raise SchemaError( | ||||
"objects containing a $ref should only have one item") | ||||
Jessica B. Hamrick
|
r16335 | pointer = jsonpointer.resolve_pointer(schema, ref) | ||
resolved = resolve_ref(pointer, schema=schema) | ||||
Jessica B. Hamrick
|
r16332 | else: | ||
Jessica B. Hamrick
|
r16335 | resolved[key] = resolve_ref(ref, schema=schema) | ||
# otherwise it's a normal object, so just return it | ||||
Jessica B. Hamrick
|
r16332 | else: | ||
Jessica B. Hamrick
|
r16335 | resolved = json | ||
return resolved | ||||