|
From: Dan G. <dkg...@lb...> - 2008-05-09 12:22:45
|
Hi,
I have a situation where there is some shared information across a
couple of configuration files and I'd like to include one config file in
another (one level of include is fine). I would welcome clever and/or
built-in solutions to this problem. But I thought I would share; below
is my ConfigObj subclass that I use (as a drop-in replacement to
ConfigObj) to solve it. Note that one thing missing from this solution
is proper re-mapping of files and line numbers in error messages.
-Dan
class IncConfigObj(configobj.ConfigObj):
"""Recognize and process '@include <file>' directives
transparently. Do not deal with recursive references, i.e.
ignore @includes inside included files.
"""
def __init__(self, infile, **kw):
"""Take same arguments as ConfigObj, but in the case of a file
object or filename, process @include statements in the file.
"""
if not isinstance(infile, str) and not hasattr(infile, 'read'):
arg = infile # pass to ConfigObj unmodified
# yes, it's a file-like-object or string (filename)
else:
arg = [ ]
if isinstance(infile, file):
f = infile
else:
f = file(infile)
# walk through input file
for line in f:
# look for include directive
if line.strip().startswith('@include'):
# open the include file
inc_path = line.strip().split(None,1)[1]
try:
f = file(inc_path)
except IOError,E:
raise IOError("opening included file "
"'%s': %s" % (inc_path, E))
# include the given file
for inc_line in f:
arg.append(inc_line)
# otherwise just keep going
else:
arg.append(line)
configobj.ConfigObj.__init__(self, arg, **kw)
--
Dan Gunter. voice:510-495-2504 fax:510-486-6363 dsd.lbl.gov/~dang
|
|
From: Michael F. <fuz...@vo...> - 2008-05-09 12:33:31
|
Hello Dan, The section method 'merge' can be used to merge config files that are read in separately. At least if you read them in individually the error messages will be correct. Michael Foord http://www.ironpythoninaction.com/ Dan Gunter wrote: > Hi, > > I have a situation where there is some shared information across a > couple of configuration files and I'd like to include one config file in > another (one level of include is fine). I would welcome clever and/or > built-in solutions to this problem. But I thought I would share; below > is my ConfigObj subclass that I use (as a drop-in replacement to > ConfigObj) to solve it. Note that one thing missing from this solution > is proper re-mapping of files and line numbers in error messages. > > -Dan > > class IncConfigObj(configobj.ConfigObj): > """Recognize and process '@include <file>' directives > transparently. Do not deal with recursive references, i.e. > ignore @includes inside included files. > """ > def __init__(self, infile, **kw): > """Take same arguments as ConfigObj, but in the case of a file > object or filename, process @include statements in the file. > """ > > if not isinstance(infile, str) and not hasattr(infile, 'read'): > arg = infile # pass to ConfigObj unmodified > # yes, it's a file-like-object or string (filename) > else: > arg = [ ] > if isinstance(infile, file): > f = infile > else: > f = file(infile) > # walk through input file > for line in f: > # look for include directive > if line.strip().startswith('@include'): > # open the include file > inc_path = line.strip().split(None,1)[1] > try: > f = file(inc_path) > except IOError,E: > raise IOError("opening included file " > "'%s': %s" % (inc_path, E)) > # include the given file > for inc_line in f: > arg.append(inc_line) > # otherwise just keep going > else: > arg.append(line) > configobj.ConfigObj.__init__(self, arg, **kw) > > |
|
From: Dan G. <dkg...@lb...> - 2008-05-09 14:15:44
|
Michael Foord wrote: > Hello Dan, > > The section method 'merge' can be used to merge config files that are > read in separately. At least if you read them in individually the error > messages will be correct. > > Aha! Thanks for the suggestion. One trick though is that in order to handle the case where A includes B and C, and C uses some values from B, I had to go ahead and merge the include files with each other as well. Anyways, my new-and-improved version, complete with proper error reporting, is below. Any further suggestions for improvement would of course be appreciated. Hopefully someone else gets some mileage out of this too.. Thanks, -Dan > Michael Foord > http://www.ironpythoninaction.com/ > import configobj class IncConfigObj(configobj.ConfigObj): """Recognize and process '#@include <file>' directives transparently. Do not deal with recursive references, i.e. ignore directives inside included files. """ def __init__(self, infile, **kw): """Take same arguments as ConfigObj, but in the case of a file object or filename, process #@include statements in the file. """ configobj.ConfigObj.__init__(self, infile, **kw) if isinstance(infile,str) or hasattr(infile,'read'): if hasattr(infile, 'read'): f = infile f.seek(0) # rewind to start of file else: f = file(infile) # walk through input file included = { } # combination of all included files for line in f: # look for include directive s = line.strip() if s.startswith('#') and \ s[1:].strip().startswith('@include'): # open and read the include file inc_path = s[1:].strip().split(None,1)[1] try: inc = configobj.ConfigObj(inc_path, **kw) except configobj.ConfigObjError, E: raise configobj.ConfigObjError( "in included file '%s': %s" % (inc_path, E)) # merge in previous included file(s) inc.merge(included) included = inc # merge included files into the top-level self.merge(included) -- Dan Gunter. voice:510-495-2504 fax:510-486-6363 dsd.lbl.gov/~dang |