configloader.py
111 lines
| 4.0 KiB
| text/x-python
|
PythonLexer
fperez
|
r0 | # -*- coding: utf-8 -*- | ||
"""Configuration loader | ||||
Fernando Perez
|
r1853 | """ | ||
fperez
|
r0 | |||
#***************************************************************************** | ||||
fperez
|
r88 | # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu> | ||
fperez
|
r0 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#***************************************************************************** | ||||
fperez
|
r52 | import exceptions | ||
fperez
|
r0 | import os | ||
from pprint import pprint | ||||
from IPython import ultraTB | ||||
Brian Granger
|
r2030 | from IPython.utils.ipstruct import Struct | ||
Brian Granger
|
r2023 | from IPython.utils.genutils import * | ||
fperez
|
r0 | |||
class ConfigLoaderError(exceptions.Exception): | ||||
"""Exception for ConfigLoader class.""" | ||||
def __init__(self,args=None): | ||||
self.args = args | ||||
class ConfigLoader: | ||||
"""Configuration file loader capable of handling recursive inclusions and | ||||
with parametrized conflict resolution for multiply found keys.""" | ||||
def __init__(self,conflict=None,field_sep=None,reclimit=15): | ||||
"""The reclimit parameter controls the number of recursive | ||||
configuration file inclusions. This way we can stop early on (before | ||||
python's own recursion limit is hit) if there is a circular | ||||
inclusion. | ||||
- conflict: dictionary for conflict resolutions (see Struct.merge()) | ||||
""" | ||||
self.conflict = conflict | ||||
self.field_sep = field_sep | ||||
self.reset(reclimit) | ||||
def reset(self,reclimit=15): | ||||
self.reclimit = reclimit | ||||
self.recdepth = 0 | ||||
self.included = [] | ||||
def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw): | ||||
"""Load a configuration file, return the resulting Struct. | ||||
Call: load_config(fname,convert=None,conflict=None,recurse_key='') | ||||
- fname: file to load from. | ||||
- convert: dictionary of type conversions (see read_dict()) | ||||
- recurse_key: keyword in dictionary to trigger recursive file | ||||
inclusions. | ||||
""" | ||||
if self.recdepth > self.reclimit: | ||||
raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\ | ||||
'exceeded: ' + `self.recdepth` + \ | ||||
'.\nMaybe you have a circular chain of inclusions?' | ||||
self.recdepth += 1 | ||||
fname = filefind(fname,incpath) | ||||
data = Struct() | ||||
# avoid including the same file more than once | ||||
if fname in self.included: | ||||
return data | ||||
Fernando Perez
|
r1758 | Xinfo = ultraTB.AutoFormattedTB(color_scheme='NoColor') | ||
fperez
|
r0 | if convert==None and recurse_key : convert = {qwflat:recurse_key} | ||
# for production, change warn to 0: | ||||
data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1, | ||||
warn=0,no_empty=0,**kw)) | ||||
# keep track of successfully loaded files | ||||
self.included.append(fname) | ||||
Fernando Perez
|
r1758 | if recurse_key in data: | ||
fperez
|
r0 | for incfilename in data[recurse_key]: | ||
found=0 | ||||
try: | ||||
incfile = filefind(incfilename,incpath) | ||||
except IOError: | ||||
if os.name in ['nt','dos']: | ||||
try: | ||||
# Try again with '.ini' extension | ||||
incfilename += '.ini' | ||||
incfile = filefind(incfilename,incpath) | ||||
except IOError: | ||||
found = 0 | ||||
else: | ||||
found = 1 | ||||
else: | ||||
found = 0 | ||||
else: | ||||
found = 1 | ||||
if found: | ||||
try: | ||||
data.merge(self.load(incfile,convert,recurse_key, | ||||
incpath,**kw), | ||||
self.conflict) | ||||
except: | ||||
Xinfo() | ||||
warn('Problem loading included file: '+ | ||||
`incfilename` + '. Ignoring it...') | ||||
else: | ||||
warn('File `%s` not found. Included by %s' % (incfilename,fname)) | ||||
return data | ||||
# end ConfigLoader | ||||