#! /usr/bin/env python3 # encoding: utf-8 import jsmin import json class Config: def __init__(self, source=None, readonly=False): """ Can be loaded from a JSON file (str path) or from a python dict. The JSON file can contain C++ style comments. """ if type(source) == str: with open(source) as f: initial = json.loads(jsmin.jsmin(f.read())) elif source is None: initial = {} else: initial = source assert type(initial) == dict object.__setattr__(self, "raw", initial) object.__setattr__(self, "readonly", readonly) def keys(self): return self.raw.keys() def values(self): return self.raw.values() def __getitem__(self, name): return self.raw[name] def __setitem__(self, name, value): if self.readonly: raise AttributeError("object is not writable") self.raw[name] = value def __setattr__(self, name, value): if self.readonly: raise AttributeError("object is not writable") self.raw[name] = value def __getattr__(self, name): matches = [key for key in self.raw if key.replace("-", "_") == name] if matches: assert len(matches) == 1 value = self.raw[matches[0]] if type(value) == dict: return Config(value) else: return value else: raise KeyError(name) def __contains__(self, name): return name in self.raw def __repr__(self): return "Config(%s)" %(" ".join("%s=%s" %(k, "…" if type(v) == dict else v) for k, v in self.raw.items()))