You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.6 KiB
Python
188 lines
5.6 KiB
Python
from __future__ import print_function
|
|
|
|
import sys
|
|
|
|
import xml.dom.minidom
|
|
|
|
if sys.version_info[0] >= 3:
|
|
from configparser import RawConfigParser
|
|
else:
|
|
from ConfigParser import RawConfigParser
|
|
|
|
def readConfig(fileName):
|
|
cp = RawConfigParser()
|
|
fp = open(fileName, 'r')
|
|
if sys.version_info < (3, 2):
|
|
cp.readfp(fp) # pylint: disable=W1505
|
|
else:
|
|
cp.read_file(fp, fileName)
|
|
return cp
|
|
|
|
|
|
def parseXMLnode(root):
|
|
"""
|
|
Parses an XML tree starting from root node and returns a list of
|
|
tuples containing name, attributes and content of all child nodes.
|
|
"""
|
|
|
|
nodes = []
|
|
|
|
if root.hasChildNodes():
|
|
for node in [ node for node in root.childNodes
|
|
if node.nodeType==node.ELEMENT_NODE ]:
|
|
|
|
ncn = len(node.childNodes)
|
|
if ncn==0:
|
|
content = None
|
|
elif ncn==1 and node.firstChild.nodeValue:
|
|
content = node.firstChild.nodeValue.strip()
|
|
else:
|
|
content = parseXMLnode(node)
|
|
|
|
attrs = {}
|
|
if node.hasAttributes():
|
|
for i in range(node.attributes.length):
|
|
attr = node.attributes.item(i)
|
|
name = attr.nodeName
|
|
attrs[name] = attr.nodeValue.strip()
|
|
|
|
nodes.append((node.nodeName, attrs, content))
|
|
|
|
return nodes
|
|
|
|
def parseXMLfile(f):
|
|
root = xml.dom.minidom.parse(f)
|
|
x = parseXMLnode(root)
|
|
if len(x)==1:
|
|
return x[0]
|
|
# else not 1 root element, but that's cought by xml.dom.minidom.parse()
|
|
|
|
class MyConfig(dict):
|
|
|
|
def __init__(self, filename):
|
|
|
|
if filename[-4:].lower() == ".ini":
|
|
self.readINI(filename)
|
|
elif filename[-4:].lower() == ".xml":
|
|
self.readXML(filename)
|
|
else: print("XXXXXXXXXXXXXXX")
|
|
|
|
def readINI(self, filename):
|
|
config = readConfig(filename)
|
|
|
|
for sec in config.sections():
|
|
d = self[sec] = {}
|
|
for opt in config.options(sec):
|
|
d[opt] = config.get(sec, opt)
|
|
|
|
def readXML(self, filename):
|
|
# XXX XML support is only provided for testing.
|
|
name, attrs, content = parseXMLfile(filename)
|
|
assert name == "config"
|
|
for name, attrs, content in content:
|
|
assert "name" in attrs
|
|
sec = attrs["name"]
|
|
assert name == "section"
|
|
d = self[sec] = {}
|
|
|
|
for name, attrs, content in content:
|
|
if isinstance(content, list):
|
|
raise TypeError("<%s> elements can't have children" % name)
|
|
|
|
if name == "string":
|
|
tmp = str(content)
|
|
elif name == "int":
|
|
tmp = int(content)
|
|
elif name == "float":
|
|
tmp = float(content)
|
|
else:
|
|
raise NameError("illegal tag '%s'" % name)
|
|
|
|
if not "name" in attrs:
|
|
raise NameError("missing 'name' attribute in <%s>" % name)
|
|
opt = attrs["name"]
|
|
d[opt] = tmp
|
|
|
|
|
|
class ConfigINI(dict):
|
|
|
|
def __init__(self, filename, mandatory=None):
|
|
self.read(filename)
|
|
if not isinstance(mandatory,list):
|
|
mandatory = []
|
|
self.mandatory = mandatory
|
|
|
|
def read(self, filename):
|
|
config = readConfig(filename)
|
|
|
|
for sec in config.sections():
|
|
d = self[sec] = {}
|
|
for opt in config.options(sec):
|
|
d[opt] = config.get(sec, opt)
|
|
|
|
def fillDefault(self, defaultSection="default"):
|
|
default = self[defaultSection]
|
|
|
|
for section in self:
|
|
if section == defaultSection:
|
|
continue
|
|
|
|
# for missing items, use the default
|
|
for item in default:
|
|
if item not in self[section]:
|
|
self[section][item] = default[item]
|
|
|
|
# # check for items that don't appear in the default
|
|
# for item in self[section]:
|
|
# if item not in default and item not in self.mandatory:
|
|
# msg("[%s]: unmatched item '%s'" % (section, item))
|
|
|
|
for item in self.mandatory:
|
|
if item not in self[section]:
|
|
msg("[%s]: missing item '%s'" % (section, item))
|
|
# XXX this could also be treated as a fatal error
|
|
|
|
|
|
class ConfigXML(MyConfig):
|
|
|
|
def __init__(self, filename):
|
|
self.read(filename)
|
|
|
|
def read(self, filename):
|
|
# XXX XML support is only provided for testing.
|
|
name, attrs, content = parseXMLfile(filename)
|
|
assert name == "config"
|
|
for name, attrs, content in content:
|
|
assert "name" in attrs
|
|
sec = attrs["name"]
|
|
assert name == "section"
|
|
d = self[sec] = {}
|
|
|
|
for name, attrs, content in content:
|
|
if isinstance(content, list):
|
|
raise TypeError("<%s> elements can't have children" % name)
|
|
|
|
if name == "string":
|
|
tmp = str(content)
|
|
elif name == "int":
|
|
tmp = int(content)
|
|
elif name == "float":
|
|
tmp = float(content)
|
|
else:
|
|
raise NameError("illegal tag '%s'" % name)
|
|
|
|
if not "name" in attrs:
|
|
raise NameError("missing 'name' attribute in <%s>" % name)
|
|
opt = attrs["name"]
|
|
d[opt] = tmp
|
|
|
|
|
|
if __name__ == '__main__':
|
|
for f in "test.ini", "test.xml":
|
|
print("#### filename=", f)
|
|
config = MyConfig(f)
|
|
print(config)
|
|
for section in config:
|
|
print(section, config[section])
|
|
|