import json
import jsoncomment


class Config:
    def __init_config_from_file(self, path):
        def add_dict(config, d):
            for k, v in d.items():
                if k in config and isinstance(config[k], dict) and isinstance(v, dict):
                    add_dict(config=config[k], d=v)
                else:
                    config[k] = v
        with open(path) as f:
            add_dict(config=self.__config,
                     d=jsoncomment.JsonComment(json).loads(f.read()))

    def __init__(self, config):
        self.__config = config

    def __getitem__(self, path):
        config = self.__config
        keys = path.split('.')
        try:
            for key in keys[:-1]:
                value = config[key]
                if isinstance(value, dict):
                    config = value
                else:
                    raise KeyError
            return Config.subConfig(config[keys[-1]])
        except KeyError:
            raise KeyError(path)

    def get(self, path, default=None):
        try:
            return self.__getitem__(path)
        except KeyError:
            return default

    def __getattr__(self, key):
        return Config.subConfig(self.__config[key])

    def __str__(self):
        return self.__config.__str__()

    def __repr__(self):
        return self.__config.__repr__()

    @staticmethod
    def subConfig(value):
        if isinstance(value, dict):
            return Config(value)
        else:
            return value

    @staticmethod
    def fromfile(path, fallback_path):
        config = Config({})
        config.__init_config_from_file(fallback_path)
        if path is not None:
            config.__init_config_from_file(path)
        return config


def load(path, fallback_path):
    assert(fallback_path is not None)
    return Config.fromfile(path, fallback_path)

@@ -493,16 +493,483 @@
 ad()))%0A%0A
+    def add_defaults(self):%0A        def add_defaults(subconfig, optional, default_key='default'):%0A            default = subconfig%5Bdefault_key%5D%0A            for k, v in subconfig.items():%0A                if k != default_key:%0A                    for opt in optional:%0A                        if opt not in v:%0A                            v%5Bopt%5D = default%5Bopt%5D%0A        add_defaults(subconfig=self.__config%5B'stats'%5D,%0A                     optional=%5B'thresholds', 'levels'%5D)%0A%0A
     def 
@@ -992,16 +992,16 @@
 onfig):%0A
-
         
@@ -1363,25 +1363,26 @@
 n Config.sub
-C
+_c
 onfig(config
@@ -1656,17 +1656,18 @@
 nfig.sub
-C
+_c
 onfig(se
@@ -1842,17 +1842,18 @@
  def sub
-C
+_c
 onfig(va
@@ -1993,24 +1993,25 @@
     def from
+_
 file(path, f
@@ -2248,52 +2248,16 @@
     
-assert(fallback_path is not None)%0A    return
+config =
  Con
@@ -2264,16 +2264,17 @@
 fig.from
+_
 file(pat
@@ -2279,20 +2279,64 @@
 ath, fallback_path)%0A
+    config.add_defaults()%0A    return config%0A

Add default values to 'section.xxx' when specific not given