##// END OF EJS Templates
Merge pull request #5991 from ivanov/jsonschema-error...
Fernando Perez -
r17014:de51efca merge
parent child Browse files
Show More
@@ -1,92 +1,112 b''
1 from __future__ import print_function
1 from __future__ import print_function
2 import json
2 import json
3 import os
3 import os
4
4
5 from jsonschema import SchemaError
5 try:
6 from jsonschema import Draft3Validator as Validator
6 from jsonschema import SchemaError
7 import jsonpointer as jsonpointer
7 from jsonschema import Draft3Validator as Validator
8 except ImportError as e:
9 verbose_msg = """
10
11 IPython depends on the jsonschema package: https://pypi.python.org/pypi/jsonschema
12
13 Please install it first.
14 """
15 raise ImportError(e.message + verbose_msg)
16
17 try:
18 import jsonpointer as jsonpointer
19 except ImportError as e:
20 verbose_msg = """
21
22 IPython depends on the jsonpointer package: https://pypi.python.org/pypi/jsonpointer
23
24 Please install it first.
25 """
26 raise ImportError(e.message + verbose_msg)
27
8 from IPython.utils.py3compat import iteritems
28 from IPython.utils.py3compat import iteritems
9
29
10
30
11 from .current import nbformat, nbformat_schema
31 from .current import nbformat, nbformat_schema
12 schema_path = os.path.join(
32 schema_path = os.path.join(
13 os.path.dirname(__file__), "v%d" % nbformat, nbformat_schema)
33 os.path.dirname(__file__), "v%d" % nbformat, nbformat_schema)
14
34
15
35
16 def isvalid(nbjson):
36 def isvalid(nbjson):
17 """Checks whether the given notebook JSON conforms to the current
37 """Checks whether the given notebook JSON conforms to the current
18 notebook format schema. Returns True if the JSON is valid, and
38 notebook format schema. Returns True if the JSON is valid, and
19 False otherwise.
39 False otherwise.
20
40
21 To see the individual errors that were encountered, please use the
41 To see the individual errors that were encountered, please use the
22 `validate` function instead.
42 `validate` function instead.
23
43
24 """
44 """
25
45
26 errors = validate(nbjson)
46 errors = validate(nbjson)
27 return errors == []
47 return errors == []
28
48
29
49
30 def validate(nbjson):
50 def validate(nbjson):
31 """Checks whether the given notebook JSON conforms to the current
51 """Checks whether the given notebook JSON conforms to the current
32 notebook format schema, and returns the list of errors.
52 notebook format schema, and returns the list of errors.
33
53
34 """
54 """
35
55
36 # load the schema file
56 # load the schema file
37 with open(schema_path, 'r') as fh:
57 with open(schema_path, 'r') as fh:
38 schema_json = json.load(fh)
58 schema_json = json.load(fh)
39
59
40 # resolve internal references
60 # resolve internal references
41 schema = resolve_ref(schema_json)
61 schema = resolve_ref(schema_json)
42 schema = jsonpointer.resolve_pointer(schema, '/notebook')
62 schema = jsonpointer.resolve_pointer(schema, '/notebook')
43
63
44 # count how many errors there are
64 # count how many errors there are
45 v = Validator(schema)
65 v = Validator(schema)
46 errors = list(v.iter_errors(nbjson))
66 errors = list(v.iter_errors(nbjson))
47 return errors
67 return errors
48
68
49
69
50 def resolve_ref(json, schema=None):
70 def resolve_ref(json, schema=None):
51 """Resolve internal references within the given JSON. This essentially
71 """Resolve internal references within the given JSON. This essentially
52 means that dictionaries of this form:
72 means that dictionaries of this form:
53
73
54 {"$ref": "/somepointer"}
74 {"$ref": "/somepointer"}
55
75
56 will be replaced with the resolved reference to `/somepointer`.
76 will be replaced with the resolved reference to `/somepointer`.
57 This only supports local reference to the same JSON file.
77 This only supports local reference to the same JSON file.
58
78
59 """
79 """
60
80
61 if not schema:
81 if not schema:
62 schema = json
82 schema = json
63
83
64 # if it's a list, resolve references for each item in the list
84 # if it's a list, resolve references for each item in the list
65 if type(json) is list:
85 if type(json) is list:
66 resolved = []
86 resolved = []
67 for item in json:
87 for item in json:
68 resolved.append(resolve_ref(item, schema=schema))
88 resolved.append(resolve_ref(item, schema=schema))
69
89
70 # if it's a dictionary, resolve references for each item in the
90 # if it's a dictionary, resolve references for each item in the
71 # dictionary
91 # dictionary
72 elif type(json) is dict:
92 elif type(json) is dict:
73 resolved = {}
93 resolved = {}
74 for key, ref in iteritems(json):
94 for key, ref in iteritems(json):
75
95
76 # if the key is equal to $ref, then replace the entire
96 # if the key is equal to $ref, then replace the entire
77 # dictionary with the resolved value
97 # dictionary with the resolved value
78 if key == '$ref':
98 if key == '$ref':
79 if len(json) != 1:
99 if len(json) != 1:
80 raise SchemaError(
100 raise SchemaError(
81 "objects containing a $ref should only have one item")
101 "objects containing a $ref should only have one item")
82 pointer = jsonpointer.resolve_pointer(schema, ref)
102 pointer = jsonpointer.resolve_pointer(schema, ref)
83 resolved = resolve_ref(pointer, schema=schema)
103 resolved = resolve_ref(pointer, schema=schema)
84
104
85 else:
105 else:
86 resolved[key] = resolve_ref(ref, schema=schema)
106 resolved[key] = resolve_ref(ref, schema=schema)
87
107
88 # otherwise it's a normal object, so just return it
108 # otherwise it's a normal object, so just return it
89 else:
109 else:
90 resolved = json
110 resolved = json
91
111
92 return resolved
112 return resolved
General Comments 0
You need to be logged in to leave comments. Login now