class YTConfig: def __init__(self, defaults=None): if defaults is None: defaults = {} self.config_root = ConfigNode(None) def get(self, section, *keys, callback=None): node_or_leaf = self.config_root.get(section, *keys) if isinstance(node_or_leaf, ConfigLeaf): if callback is not None: return callback(node_or_leaf) return node_or_leaf.value return node_or_leaf def get_most_specific(self, section, *keys, **kwargs): use_fallback = "fallback" in kwargs fallback = kwargs.pop("fallback", None) try: return self.config_root.get_deepest_leaf(section, *keys) except KeyError as err: if use_fallback: return fallback else: raise err def update(self, new_values, metadata=None): if metadata is None: metadata = {} self.config_root.update(new_values, metadata) def has_section(self, section): try: self.config_root.get_child(section) return True except KeyError: return False def add_section(self, section): self.config_root.add_child(section) def remove_section(self, section): if self.has_section(section): self.config_root.remove_child(section) return True else: return False def set(self, *args, metadata=None): section, *keys, value = args if metadata is None: metadata = {"source": "runtime"} self.config_root.upsert_from_list([section] + list(keys), value, extra_data=metadata) def remove(self, *args): self.config_root.pop_leaf(args) def read(self, file_names): file_names_read = [] for fname in always_iterable(file_names): if not os.path.exists(fname): continue metadata = {"source": f"file: {fname}"} self.update(toml.load(fname), metadata=metadata) file_names_read.append(fname) return file_names_read def write(self, file_handler): value = self.config_root.as_dict() config_as_str = toml.dumps(value) try: # Assuming file_handler has a write attribute file_handler.write(config_as_str) except AttributeError: # Otherwise we expect a path to a file with open(file_handler, mode="w") as fh: fh.write(config_as_str) @staticmethod def get_global_config_file(): return os.path.join(config_dir(), "yt.toml") @staticmethod def get_local_config_file(): return os.path.join(os.path.abspath(os.curdir), "yt.toml") def __setitem__(self, args, value): section, *keys = always_iterable(args) self.set(section, *keys, value, metadata=None) def __getitem__(self, key): section, *keys = always_iterable(key) return self.get(section, *keys) def __contains__(self, item): return item in self.config_root # Add support for IPython rich display # see https://ipython.readthedocs.io/en/stable/config/integrating.html def _repr_json_(self): return self.config_root._repr_json_()
class YTConfig: def __init__(self, defaults=None): if defaults is None: defaults = {} self.config_root = ConfigNode(None) def get(self, section, *keys, callback=None, **kwargs): if callback is None: def callback(leaf): return leaf.value return self.config_root.get_leaf(section, *keys, callback=callback) def get_most_specific(self, section, *keys, **kwargs): use_fallback = "fallback" in kwargs fallback = kwargs.pop("fallback", None) try: return self.config_root.get_deepest_leaf(section, *keys) except KeyError as err: if use_fallback: return fallback else: raise err def update(self, new_values, metadata=None): if metadata is None: metadata = {} self.config_root.update(new_values, metadata) def has_section(self, section): try: self.config_root.get_child(section) return True except KeyError: return False def add_section(self, section): self.config_root.add_child(section) def remove_section(self, section): if self.has_section(section): self.config_root.remove_child(section) return True else: return False def set(self, *args, metadata=None): section, *keys, value = args if metadata is None: metadata = {"source": "runtime"} self.config_root.upsert_from_list([section] + list(keys), value, extra_data=metadata) def __setitem__(self, args, value): section, *keys = args self.set(section, *keys, value, metadata=None) def __getitem__(self, key): section, *keys = key return self.get(section, *keys) def remove(self, *args): self.config_root.pop_leaf(args) def read(self, file_names): file_names_read = [] for fname in always_iterable(file_names): if not os.path.exists(fname): continue metadata = {"source": f"file: {fname}"} self.update(toml.load(fname), metadata=metadata) file_names_read.append(fname) return file_names_read def write(self, file_handler): value = self.config_root.as_dict() config_as_str = toml.dumps(value) try: # Assuming file_handler has a write attribute file_handler.write(config_as_str) except AttributeError: # Otherwise we expect a path to a file with open(file_handler, mode="w") as fh: fh.write(config_as_str) @staticmethod def get_global_config_file(): return os.path.join(CONFIG_DIR, "yt.toml") @staticmethod def get_local_config_file(): return os.path.join(os.path.abspath(os.curdir), "yt.toml")