|
From: Matthew B. <mat...@gm...> - 2005-12-05 11:39:49
|
Hi, Just another thought. I have been browsing the different suggested replacements for ConfigParser listed on the shootout page: http://wiki.python.org/moin/ConfigParserShootout ConfigObj certainly seems to get me most of the way there, but one feature that I really miss is the ability to merge different configuration files, while stlll falling back to defaults for settings not found in the files. This is one of the desirable features listed for the ConfigParser replacement: http://wiki.python.org/moin/ConfigParserShootout#head-a1bf82289c05f5749e5b0= c6bea97f6b1d35c05cd For example, let us say I have a system configuration file, a local user configuration file and a file in the current working directory: cfg_files =3D [sys_cfg, user_cfg, pwd_cfg] I would like to be able to take any settings from pwd_cfg, then get any settings missing in pwd_cfg from user_cfg, then any still missing from sys_cfg, and any remaining options from my hardcoded defaults. In fact, this is very nice feature of cfgparse: http://cfgparse.sourceforge.net/ - you can do something like: p =3D cfgparse.ConfigParser() p.add_option('some_option', default=3DTrue) # etc for f in cfg_files: if os.path.exists(_f): p.add_file(_f) opts =3D p. parse() I would really like to be able to do something similar with ConfigObj, but my current approach is a little cludgy. At the moment, I think I have a) avoid setting defaults in my configspec b) make a separate options string list with my defaults, and c) apply my own merge function (see code snippet below). Is there a better way to do this? Thanks again, Matthew # Code snippet: def soft_merge(a, b): """ Fills values recursively in dictionary a from values in dictionary b. Any fields missing or None in a but present in b will be filled from b. Fields which are dictionaries (objects with iteritems method) will be filled recursively. We prefer a dictionary field in either a or b to a non-dictionary. """ if a is None: return b try: b_iter =3D b.iteritems() except: return a try: a_iter =3D a.iteritems() except: return b for (k,v) in b_iter: if a.has_key(k): a[k] =3D soft_merge(a[k], v) else: a[k] =3D v return a cfg_spec =3D ''' [my_section] setting1 =3D boolean() setting2 =3D boolean() """.split('\n') default_cfg =3D """ [my_section] setting1 =3D True setting2 =3D False """.split('\n') cfg_obj =3D configobj.ConfigObj; opts =3D cfg_obj(None, configspec=3Dcfg_spec) cfg_files.append(default_cfg) for f in cfg_files: opts =3D soft_merge(opts, cfg_obj(f)) |