| | import json |
| | import os |
| | from copy import deepcopy |
| | from dataclasses import dataclass |
| |
|
| |
|
| | @dataclass |
| | class BaseConfig: |
| | def clone(self): |
| | return deepcopy(self) |
| |
|
| | def inherit(self, another): |
| | """inherit common keys from a given config""" |
| | common_keys = set(self.__dict__.keys()) & set(another.__dict__.keys()) |
| | for k in common_keys: |
| | setattr(self, k, getattr(another, k)) |
| |
|
| | def propagate(self): |
| | """push down the configuration to all members""" |
| | for k, v in self.__dict__.items(): |
| | if isinstance(v, BaseConfig): |
| | v.inherit(self) |
| | v.propagate() |
| |
|
| | def save(self, save_path): |
| | """save config to json file""" |
| | dirname = os.path.dirname(save_path) |
| | if not os.path.exists(dirname): |
| | os.makedirs(dirname) |
| | conf = self.as_dict_jsonable() |
| | with open(save_path, 'w') as f: |
| | json.dump(conf, f) |
| |
|
| | def load(self, load_path): |
| | """load json config""" |
| | with open(load_path) as f: |
| | conf = json.load(f) |
| | self.from_dict(conf) |
| |
|
| | def from_dict(self, dict, strict=False): |
| | for k, v in dict.items(): |
| | if not hasattr(self, k): |
| | if strict: |
| | raise ValueError(f"loading extra '{k}'") |
| | else: |
| | print(f"loading extra '{k}'") |
| | continue |
| | if isinstance(self.__dict__[k], BaseConfig): |
| | self.__dict__[k].from_dict(v) |
| | else: |
| | self.__dict__[k] = v |
| |
|
| | def as_dict_jsonable(self): |
| | conf = {} |
| | for k, v in self.__dict__.items(): |
| | if isinstance(v, BaseConfig): |
| | conf[k] = v.as_dict_jsonable() |
| | else: |
| | if jsonable(v): |
| | conf[k] = v |
| | else: |
| | |
| | pass |
| | return conf |
| |
|
| |
|
| | def jsonable(x): |
| | try: |
| | json.dumps(x) |
| | return True |
| | except TypeError: |
| | return False |
| |
|