##// END OF EJS Templates
Return the list of errors, rather than the number of errors
Jessica B. Hamrick -
Show More
@@ -1,238 +1,238 b''
1 1 """The official API for working with notebooks in the current format version.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 * Jonathan Frederic
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2008-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from __future__ import print_function
21 21
22 22 from xml.etree import ElementTree as ET
23 23 import re
24 24
25 25 from IPython.utils.py3compat import unicode_type
26 26
27 27 from IPython.nbformat.v3 import (
28 28 NotebookNode,
29 29 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
30 30 parse_filename, new_metadata, new_author, new_heading_cell, nbformat,
31 31 nbformat_minor, nbformat_schema, to_notebook_json
32 32 )
33 33 from IPython.nbformat import v3 as _v_latest
34 34
35 35 from .reader import reads as reader_reads
36 36 from .reader import versions
37 37 from .convert import convert
38 38 from .validator import validate
39 39
40 40 import logging
41 41 logger = logging.getLogger('NotebookApp')
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Code
45 45 #-----------------------------------------------------------------------------
46 46
47 47 current_nbformat = nbformat
48 48 current_nbformat_minor = nbformat_minor
49 49 current_nbformat_module = _v_latest.__name__
50 50
51 51
52 52 def docstring_nbformat_mod(func):
53 53 """Decorator for docstrings referring to classes/functions accessed through
54 54 nbformat.current.
55 55
56 56 Put {nbformat_mod} in the docstring in place of 'IPython.nbformat.v3'.
57 57 """
58 58 func.__doc__ = func.__doc__.format(nbformat_mod=current_nbformat_module)
59 59 return func
60 60
61 61
62 62 class NBFormatError(ValueError):
63 63 pass
64 64
65 65
66 66 def parse_py(s, **kwargs):
67 67 """Parse a string into a (nbformat, string) tuple."""
68 68 nbf = current_nbformat
69 69 nbm = current_nbformat_minor
70 70
71 71 pattern = r'# <nbformat>(?P<nbformat>\d+[\.\d+]*)</nbformat>'
72 72 m = re.search(pattern,s)
73 73 if m is not None:
74 74 digits = m.group('nbformat').split('.')
75 75 nbf = int(digits[0])
76 76 if len(digits) > 1:
77 77 nbm = int(digits[1])
78 78
79 79 return nbf, nbm, s
80 80
81 81
82 82 def reads_json(nbjson, **kwargs):
83 83 """Read a JSON notebook from a string and return the NotebookNode
84 84 object. Report if any JSON format errors are detected.
85 85
86 86 """
87 87 nb = reader_reads(nbjson, **kwargs)
88 88 nb_current = convert(nb, current_nbformat)
89 num_errors = validate(nb_current)
90 if num_errors > 0:
89 errors = validate(nb_current)
90 if len(errors) > 0:
91 91 logger.error(
92 92 "Notebook JSON is invalid (%d errors detected during read)",
93 num_errors)
93 len(errors))
94 94 return nb_current
95 95
96 96
97 97 def writes_json(nb, **kwargs):
98 98 """Take a NotebookNode object and write out a JSON string. Report if
99 99 any JSON format errors are detected.
100 100
101 101 """
102 num_errors = validate(nb)
103 if num_errors > 0:
102 errors = validate(nb)
103 if len(errors) > 0:
104 104 logger.error(
105 105 "Notebook JSON is invalid (%d errors detected during write)",
106 num_errors)
106 len(errors))
107 107 nbjson = versions[current_nbformat].writes_json(nb, **kwargs)
108 108 return nbjson
109 109
110 110
111 111 def reads_py(s, **kwargs):
112 112 """Read a .py notebook from a string and return the NotebookNode object."""
113 113 nbf, nbm, s = parse_py(s, **kwargs)
114 114 if nbf in (2, 3):
115 115 nb = versions[nbf].to_notebook_py(s, **kwargs)
116 116 else:
117 117 raise NBFormatError('Unsupported PY nbformat version: %i' % nbf)
118 118 return nb
119 119
120 120
121 121 def writes_py(nb, **kwargs):
122 122 # nbformat 3 is the latest format that supports py
123 123 return versions[3].writes_py(nb, **kwargs)
124 124
125 125
126 126 # High level API
127 127
128 128
129 129 def reads(s, format, **kwargs):
130 130 """Read a notebook from a string and return the NotebookNode object.
131 131
132 132 This function properly handles notebooks of any version. The notebook
133 133 returned will always be in the current version's format.
134 134
135 135 Parameters
136 136 ----------
137 137 s : unicode
138 138 The raw unicode string to read the notebook from.
139 139 format : (u'json', u'ipynb', u'py')
140 140 The format that the string is in.
141 141
142 142 Returns
143 143 -------
144 144 nb : NotebookNode
145 145 The notebook that was read.
146 146 """
147 147 format = unicode_type(format)
148 148 if format == u'json' or format == u'ipynb':
149 149 return reads_json(s, **kwargs)
150 150 elif format == u'py':
151 151 return reads_py(s, **kwargs)
152 152 else:
153 153 raise NBFormatError('Unsupported format: %s' % format)
154 154
155 155
156 156 def writes(nb, format, **kwargs):
157 157 """Write a notebook to a string in a given format in the current nbformat version.
158 158
159 159 This function always writes the notebook in the current nbformat version.
160 160
161 161 Parameters
162 162 ----------
163 163 nb : NotebookNode
164 164 The notebook to write.
165 165 format : (u'json', u'ipynb', u'py')
166 166 The format to write the notebook in.
167 167
168 168 Returns
169 169 -------
170 170 s : unicode
171 171 The notebook string.
172 172 """
173 173 format = unicode_type(format)
174 174 if format == u'json' or format == u'ipynb':
175 175 return writes_json(nb, **kwargs)
176 176 elif format == u'py':
177 177 return writes_py(nb, **kwargs)
178 178 else:
179 179 raise NBFormatError('Unsupported format: %s' % format)
180 180
181 181
182 182 def read(fp, format, **kwargs):
183 183 """Read a notebook from a file and return the NotebookNode object.
184 184
185 185 This function properly handles notebooks of any version. The notebook
186 186 returned will always be in the current version's format.
187 187
188 188 Parameters
189 189 ----------
190 190 fp : file
191 191 Any file-like object with a read method.
192 192 format : (u'json', u'ipynb', u'py')
193 193 The format that the string is in.
194 194
195 195 Returns
196 196 -------
197 197 nb : NotebookNode
198 198 The notebook that was read.
199 199 """
200 200 return reads(fp.read(), format, **kwargs)
201 201
202 202
203 203 def write(nb, fp, format, **kwargs):
204 204 """Write a notebook to a file in a given format in the current nbformat version.
205 205
206 206 This function always writes the notebook in the current nbformat version.
207 207
208 208 Parameters
209 209 ----------
210 210 nb : NotebookNode
211 211 The notebook to write.
212 212 fp : file
213 213 Any file-like object with a write method.
214 214 format : (u'json', u'ipynb', u'py')
215 215 The format to write the notebook in.
216 216
217 217 Returns
218 218 -------
219 219 s : unicode
220 220 The notebook string.
221 221 """
222 222 return fp.write(writes(nb, format, **kwargs))
223 223
224 224 def _convert_to_metadata():
225 225 """Convert to a notebook having notebook metadata."""
226 226 import glob
227 227 for fname in glob.glob('*.ipynb'):
228 228 print('Converting file:',fname)
229 229 with open(fname,'r') as f:
230 230 nb = read(f,u'json')
231 231 md = new_metadata()
232 232 if u'name' in nb:
233 233 md.name = nb.name
234 234 del nb[u'name']
235 235 nb.metadata = md
236 236 with open(fname,'w') as f:
237 237 write(nb, f, u'json')
238 238
@@ -1,97 +1,91 b''
1 1 from __future__ import print_function
2 2 import json
3 3 import os
4 4
5 5 from IPython.external.jsonschema import Draft3Validator, SchemaError
6 6 import IPython.external.jsonpointer as jsonpointer
7 7 from IPython.utils.py3compat import iteritems
8 8
9 9
10 10 from .current import nbformat, nbformat_schema
11 11 schema_path = os.path.join(
12 12 os.path.dirname(__file__), "v%d" % nbformat, nbformat_schema)
13 13
14 14
15 def isvalid(nbjson, verbose=False):
15 def isvalid(nbjson):
16 16 """Checks whether the given notebook JSON conforms to the current
17 17 notebook format schema. Returns True if the JSON is valid, and
18 18 False otherwise.
19 19
20 If `verbose` is set, then print out each error that is detected.
20 To see the individual errors that were encountered, please use the
21 `validate` function instead.
21 22
22 23 """
23 24
24 errors = validate(nbjson, verbose=verbose)
25 errors = validate(nbjson)
25 26 return errors == 0
26 27
27 28
28 def validate(nbjson, verbose=False):
29 def validate(nbjson):
29 30 """Checks whether the given notebook JSON conforms to the current
30 notebook format schema, and returns the number of errors.
31
32 If `verbose` is set, then print out each error that is detected.
31 notebook format schema, and returns the list of errors.
33 32
34 33 """
35 34
36 35 # load the schema file
37 36 with open(schema_path, 'r') as fh:
38 37 schema_json = json.load(fh)
39 38
40 39 # resolve internal references
41 40 v3schema = resolve_ref(schema_json)
42 41 v3schema = jsonpointer.resolve_pointer(v3schema, '/notebook')
43 42
44 43 # count how many errors there are
45 errors = 0
46 44 v = Draft3Validator(v3schema)
47 for error in v.iter_errors(nbjson):
48 errors = errors + 1
49 if verbose:
50 print(error)
51
45 errors = [e for e in v.iter_errors(nbjson)]
52 46 return errors
53 47
54 48
55 49 def resolve_ref(json, schema=None):
56 50 """Resolve internal references within the given JSON. This essentially
57 51 means that dictionaries of this form:
58 52
59 53 {"$ref": "/somepointer"}
60 54
61 55 will be replaced with the resolved reference to `/somepointer`.
62 56 This only supports local reference to the same JSON file.
63 57
64 58 """
65 59
66 60 if not schema:
67 61 schema = json
68 62
69 63 # if it's a list, resolve references for each item in the list
70 64 if type(json) is list:
71 65 resolved = []
72 66 for item in json:
73 67 resolved.append(resolve_ref(item, schema=schema))
74 68
75 69 # if it's a dictionary, resolve references for each item in the
76 70 # dictionary
77 71 elif type(json) is dict:
78 72 resolved = {}
79 73 for key, ref in iteritems(json):
80 74
81 75 # if the key is equal to $ref, then replace the entire
82 76 # dictionary with the resolved value
83 77 if key == '$ref':
84 78 if len(json) != 1:
85 79 raise SchemaError(
86 80 "objects containing a $ref should only have one item")
87 81 pointer = jsonpointer.resolve_pointer(schema, ref)
88 82 resolved = resolve_ref(pointer, schema=schema)
89 83
90 84 else:
91 85 resolved[key] = resolve_ref(ref, schema=schema)
92 86
93 87 # otherwise it's a normal object, so just return it
94 88 else:
95 89 resolved = json
96 90
97 91 return resolved
General Comments 0
You need to be logged in to leave comments. Login now