7
7
import pprint
8
8
import sys
9
9
import warnings
10
+ from copy import deepcopy
10
11
11
12
from ipython_genutils .importstring import import_item
12
13
from .json_compat import get_current_validator , ValidationError
13
14
from .reader import get_version , reads
14
15
from .corpus .words import generate_corpus_id
16
+ from .warnings import MissingIDFieldWarning
15
17
16
18
validators = {}
17
19
@@ -229,15 +231,71 @@ def better_validation_error(error, version, version_minor):
229
231
return NotebookValidationError (error , ref )
230
232
231
233
232
- def validate (nbdict = None , ref = None , version = None , version_minor = None ,
233
- relax_add_props = False , nbjson = None ):
234
+ def normalize (nbdict , version , version_minor ):
235
+ """
236
+ EXPERIMENTAL
237
+
238
+ normalise a notebook prior to validation.
239
+
240
+ This tries to implement a couple of normalisation steps to standardise
241
+ notebooks and make validation easier.
242
+
243
+ You should in general not rely on this function and make sure the notebooks
244
+ that reach nbformat are already in a normal form.
245
+
246
+ Parameters
247
+ ----------
248
+ nbdict : dict
249
+ notebook document
250
+ version : int
251
+ version_minor : int
252
+
253
+ Returns
254
+ -------
255
+ changes : int
256
+ number of changes in the notebooks
257
+ notebook : dict
258
+ deep-copy of the original object with relevant changes.
259
+
260
+ """
261
+ nbdict = deepcopy (nbdict )
262
+ return _normalize (deepcopy (nbdict ))
263
+
264
+ def _normalize (nbdict , version , version_minor ):
265
+ changes = 0
266
+
267
+ if version >= 4 and version_minor >= 5 :
268
+ # if we support cell ids ensure default ids are provided
269
+ for cell in nbdict ["cells" ]:
270
+ if "id" not in cell :
271
+ changes += 1
272
+ warnings .warn (
273
+ "Code cell is missing an id field, this will become"
274
+ " a hard error in future nbformat versions. You may want"
275
+ " to use `normalize()` on your notebooks before validations"
276
+ " (available since nbformat 5.1.4). Previous of nbformat"
277
+ " are also mutating their arguments, and will stop to do so"
278
+ " in the future." ,
279
+ MissingIDFieldWarning ,
280
+ stacklevel = 3 ,
281
+ )
282
+ # Generate cell ids if any are missing
283
+ cell ['id' ] = generate_corpus_id ()
284
+ return changes , nbdict
285
+
286
+ def validate (nbdict = None , ref :str = None , version = None , version_minor = None ,
287
+ relax_add_props = False , nbjson = None ) -> None :
234
288
"""Checks whether the given notebook dict-like object
235
289
conforms to the relevant notebook format schema.
236
290
237
-
291
+ Parameters
292
+ ----------
293
+ ref : optional, str
294
+ reference to the subset of the schema we want to validate against.
295
+ for example ``"markdown_cell"``, `"code_cell"` ....
238
296
Raises ValidationError if not valid.
239
297
"""
240
-
298
+ assert isinstance ( ref , str ) or ref is None
241
299
# backwards compatibility for nbjson argument
242
300
if nbdict is not None :
243
301
pass
@@ -257,13 +315,8 @@ def validate(nbdict=None, ref=None, version=None, version_minor=None,
257
315
# if ref is specified, and we don't have a version number, assume we're validating against 1.0
258
316
if version is None :
259
317
version , version_minor = 1 , 0
260
-
261
- if ref is None and version >= 4 and version_minor >= 5 :
262
- # if we support cell ids ensure default ids are provided
263
- for cell in nbdict ['cells' ]:
264
- if 'id' not in cell :
265
- # Generate cell ids if any are missing
266
- cell ['id' ] = generate_corpus_id ()
318
+ if ref is None :
319
+ _normalize (nbdict , version , version_minor )
267
320
268
321
for error in iter_validate (nbdict , ref = ref , version = version ,
269
322
version_minor = version_minor ,
0 commit comments