manager.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """Manager to read and modify config data in JSON files.
  2. """
  3. # Copyright (c) IPython Development Team.
  4. # Distributed under the terms of the Modified BSD License.
  5. import errno
  6. import io
  7. import json
  8. import os
  9. from six import PY3
  10. from traitlets.config import LoggingConfigurable
  11. from traitlets.traitlets import Unicode
  12. def recursive_update(target, new):
  13. """Recursively update one dictionary using another.
  14. None values will delete their keys.
  15. """
  16. for k, v in new.items():
  17. if isinstance(v, dict):
  18. if k not in target:
  19. target[k] = {}
  20. recursive_update(target[k], v)
  21. if not target[k]:
  22. # Prune empty subdicts
  23. del target[k]
  24. elif v is None:
  25. target.pop(k, None)
  26. else:
  27. target[k] = v
  28. class BaseJSONConfigManager(LoggingConfigurable):
  29. """General JSON config manager
  30. Deals with persisting/storing config in a json file
  31. """
  32. config_dir = Unicode('.')
  33. def ensure_config_dir_exists(self):
  34. try:
  35. os.makedirs(self.config_dir, 0o755)
  36. except OSError as e:
  37. if e.errno != errno.EEXIST:
  38. raise
  39. def file_name(self, section_name):
  40. return os.path.join(self.config_dir, section_name+'.json')
  41. def get(self, section_name):
  42. """Retrieve the config data for the specified section.
  43. Returns the data as a dictionary, or an empty dictionary if the file
  44. doesn't exist.
  45. """
  46. filename = self.file_name(section_name)
  47. if os.path.isfile(filename):
  48. with io.open(filename, encoding='utf-8') as f:
  49. return json.load(f)
  50. else:
  51. return {}
  52. def set(self, section_name, data):
  53. """Store the given config data.
  54. """
  55. filename = self.file_name(section_name)
  56. self.ensure_config_dir_exists()
  57. if PY3:
  58. f = io.open(filename, 'w', encoding='utf-8')
  59. else:
  60. f = open(filename, 'wb')
  61. with f:
  62. json.dump(data, f, indent=2)
  63. def update(self, section_name, new_data):
  64. """Modify the config section by recursively updating it with new_data.
  65. Returns the modified config data as a dictionary.
  66. """
  67. data = self.get(section_name)
  68. recursive_update(data, new_data)
  69. self.set(section_name, data)
  70. return data