notebooknode.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. """NotebookNode - adding attribute access to dicts"""
  2. from __future__ import annotations
  3. from collections.abc import Mapping
  4. from ._struct import Struct
  5. class NotebookNode(Struct):
  6. """A dict-like node with attribute-access"""
  7. def __setitem__(self, key, value):
  8. """Set an item on the notebook."""
  9. if isinstance(value, Mapping) and not isinstance(value, NotebookNode):
  10. value = from_dict(value)
  11. super().__setitem__(key, value)
  12. def update(self, *args, **kwargs):
  13. """
  14. A dict-like update method based on CPython's MutableMapping `update`
  15. method.
  16. """
  17. if len(args) > 1:
  18. raise TypeError("update expected at most 1 arguments, got %d" % len(args))
  19. if args:
  20. other = args[0]
  21. if isinstance(other, Mapping): # noqa: SIM114
  22. for key in other:
  23. self[key] = other[key]
  24. elif hasattr(other, "keys"):
  25. for key in other:
  26. self[key] = other[key]
  27. else:
  28. for key, value in other:
  29. self[key] = value
  30. for key, value in kwargs.items():
  31. self[key] = value
  32. def from_dict(d):
  33. """Convert dict to dict-like NotebookNode
  34. Recursively converts any dict in the container to a NotebookNode.
  35. This does not check that the contents of the dictionary make a valid
  36. notebook or part of a notebook.
  37. """
  38. if isinstance(d, dict):
  39. return NotebookNode({k: from_dict(v) for k, v in d.items()})
  40. if isinstance(d, (tuple, list)):
  41. return [from_dict(i) for i in d]
  42. return d