nbjson.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. """Read and write notebooks in JSON format."""
  2. # Copyright (c) IPython Development Team.
  3. # Distributed under the terms of the Modified BSD License.
  4. import copy
  5. import json
  6. from ipython_genutils import py3compat
  7. from ..notebooknode import from_dict
  8. from .rwbase import (
  9. NotebookReader, NotebookWriter, rejoin_lines, split_lines, strip_transient
  10. )
  11. class BytesEncoder(json.JSONEncoder):
  12. """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""
  13. def default(self, obj):
  14. if isinstance(obj, bytes):
  15. return obj.decode('ascii')
  16. return json.JSONEncoder.default(self, obj)
  17. class JSONReader(NotebookReader):
  18. def reads(self, s, **kwargs):
  19. """Read a JSON string into a Notebook object"""
  20. nb = json.loads(s, **kwargs)
  21. nb = self.to_notebook(nb, **kwargs)
  22. return nb
  23. def to_notebook(self, d, **kwargs):
  24. """Convert a disk-format notebook dict to in-memory NotebookNode
  25. handles multi-line values as strings, scrubbing of transient values, etc.
  26. """
  27. nb = from_dict(d)
  28. nb = rejoin_lines(nb)
  29. nb = strip_transient(nb)
  30. return nb
  31. class JSONWriter(NotebookWriter):
  32. def writes(self, nb, **kwargs):
  33. """Serialize a NotebookNode object as a JSON string"""
  34. kwargs['cls'] = BytesEncoder
  35. kwargs['indent'] = 1
  36. kwargs['sort_keys'] = True
  37. kwargs['separators'] = (',',': ')
  38. kwargs.setdefault('ensure_ascii', False)
  39. # don't modify in-memory dict
  40. nb = copy.deepcopy(nb)
  41. if kwargs.pop('split_lines', True):
  42. nb = split_lines(nb)
  43. nb = strip_transient(nb)
  44. return py3compat.cast_unicode_py2(json.dumps(nb, **kwargs), 'utf-8')
  45. _reader = JSONReader()
  46. _writer = JSONWriter()
  47. reads = _reader.reads
  48. read = _reader.read
  49. to_notebook = _reader.to_notebook
  50. write = _writer.write
  51. writes = _writer.writes