aboutsummaryrefslogtreecommitdiff
path: root/util/Config.py
blob: 040e9b082902eb8033779e41619b366fbae7c25d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from xml.etree.ElementTree import *
import sys
import xml
import pdb
import util.Strings as Strings
from logger import main_log, exception_log
classArgsMem = {}
CONFIG_PATH = 'config/'
def loadParamRequirementDict(className):
    if not className in classArgsMem: #WOO CACHING
        classArgsMem[className] = fileToDict(CONFIG_PATH + className) 
    return classArgsMem[className]
#Loads a config file.  If its an xml file, inheritances are automatically resolved.
def loadConfigFile(fileName): #TODO: error handling etc.
    try:
        if '.params' in fileName:
            return fileToDict(fileName)
        if '.xml' in fileName:
            config = ElementTree() #use .fromstring, and resolve xincludes
            config.parse(fileName)
            config = ElementTree(resolveConfigInheritance(config.getroot()))
            return config
    except Exception as inst:
        main_log.error('Error loading config file ' + fileName)#, inst) TODO: log exception too
        return None
#Takes an Element or an ElementTree.  If it is a tree, it returns its root.  Otherwise, just returns
#it
def getElement(el):
    if xml.etree.ElementTree.iselement(el):
        return el
    elif el.__class__ == ElementTree:
        return el.getroot()
def compositeXMLTrees(parentTree, overridingTree): #TODO: break up into sub-methods, change it to
#use .find()
    #type checking -- convert ElementTrees to their root elements
    if parentTree == None:
        return overridingTree
    if overridingTree == None:
        return parentTree
    parentTree = getElement(parentTree)
    overridingTree = getElement(overridingTree)
    parentItems = parentTree.getchildren()
    overrideItems = overridingTree.getchildren()
    #first, lets figure out what tags we have in the override tree:
    tagCollection = [el.tag for el in overrideItems] #we can speed this up with a dict if necessary
    for item in parentItems:
        if not item.tag in tagCollection: #no override 
            overridingTree.insert(-1, item) #insert the new item at the end
        else:
            #do we merge or replace?
            intersectingElements = findElementsByTag(item.tag, overrideItems)
            if len(intersectingElements) > 1:
                main_log.warn('ABUSE!  Override of multiple items isn\'t well defined.  Don\'t do\
                it!')
            interEl = intersectingElements[0]
            mode = 'Replace'
            if Strings.OVERRIDE_BEHAVIOR in interEl.attrib:
                mode = interEl.attrib[Strings.OVERRIDE_BEHAVIOR] 
            if mode != 'Replace' and mode != 'Merge':
                main_log.warn('Bad Override Mode.  Choosing to replace.')
                mode = 'Replace'
            if mode == 'Replace':
                pass #we don't need to do anything
            if mode == 'Merge': 
                interEl = compositeXMLTrees(item, interEl)
    for item in overrideItems: #resolve appendages
        if item.tag == 'APPEND':
            children = item.getchildren()
            for child in children:
                overrideItems.insert(-1, child)
            overrideItems.remove(item)
    return overridingTree
def findElementsByTag(tag, eList):
    return [el for el in eList if el.tag == tag]
def fileToDict(fileName):
    fileText = ''
    try:
        with open(fileName) as f:
            for line in f:
                fileText += line.rstrip('\n').lstrip('\t') + ' ' 
    except IOError:
        exception_log.exception('Failure reading ' + fileName)
        return {}
    if fileText == '':
        return {}
    try:
        resultDict = eval(fileText)
        main_log.info(fileName + ' read and parsed')
        return resultDict
    except:
        exception_log.info(fileName + ' is not a well formed python dict.  Parsing failed') 
    return eval(fileText)
#parses arguments into python objects if possible, otherwise leaves as strings
def generateArgDict(parentNode, recurse=False):
    args = {}
    for arg in parentNode.getchildren():
        key = arg.tag
        if arg.getchildren() != []:
            value = generateArgDict(arg, True)
        else:
            #convert into python if possible, otherwise don't
            try:
                value = eval(arg.text)
            except (NameError,SyntaxError):
                value = str(arg.text)
        if key in args: #build of lists of like-elements
            if type(args[key]) != type([]):
                args[key] = [args[key]]
            args[key].append(value)
        else:
            args[key]=value
    #if we should be a list but we aren't:
    if len(args.keys()) == 1 and recurse:
        return args[args.keys()[0]]
    return args

def resolveConfigInheritance(el):
    parentClass = el.find('InheritsFrom')
    if parentClass != None:
        parentTree = loadConfigFile(parentClass.text)
        if parentTree == None:
            main_log.warn('Inheritance Failed.  ' + parentClass.text + 'does not exist')
            main_log.error('Inheritance Failed.  ' + parentClass.text + 'does not exist')
            return el
        el = compositeXMLTrees(el, parentTree) 
        el.remove(parentClass) #get rid of the inheritance flag
    return el