Mini Shell
"""Manager to read and modify config data in JSON files.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from __future__ import annotations
import errno
import json
import os
from typing import Any
from traitlets.config import LoggingConfigurable
from traitlets.traitlets import Unicode
def recursive_update(target: dict[Any, Any], new: dict[Any, Any]) -> None:
"""Recursively update one dictionary using another.
None values will delete their keys.
"""
for k, v in new.items():
if isinstance(v, dict):
if k not in target:
target[k] = {}
recursive_update(target[k], v)
if not target[k]:
# Prune empty subdicts
del target[k]
elif v is None:
target.pop(k, None)
else:
target[k] = v
class BaseJSONConfigManager(LoggingConfigurable):
"""General JSON config manager
Deals with persisting/storing config in a json file
"""
config_dir = Unicode(".")
def ensure_config_dir_exists(self) -> None:
try:
os.makedirs(self.config_dir, 0o755)
except OSError as e:
if e.errno != errno.EEXIST:
raise
def file_name(self, section_name: str) -> str:
return os.path.join(self.config_dir, section_name + ".json")
def get(self, section_name: str) -> Any:
"""Retrieve the config data for the specified section.
Returns the data as a dictionary, or an empty dictionary if the file
doesn't exist.
"""
filename = self.file_name(section_name)
if os.path.isfile(filename):
with open(filename, encoding="utf-8") as f:
return json.load(f)
else:
return {}
def set(self, section_name: str, data: Any) -> None:
"""Store the given config data."""
filename = self.file_name(section_name)
self.ensure_config_dir_exists()
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
def update(self, section_name: str, new_data: Any) -> Any:
"""Modify the config section by recursively updating it with new_data.
Returns the modified config data as a dictionary.
"""
data = self.get(section_name)
recursive_update(data, new_data)
self.set(section_name, data)
return data
Zerion Mini Shell 1.0