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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
from xml.etree.ElementTree import *
import sys
import xml
import pdb
import util.Strings as Strings
import util.Search as Search
from logger import main_log, exception_log
classArgsMem = {}
CONFIG_PATH = 'config/'
DEFAULT_OVERRIDE_MODE = 'Merge'
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()
config.parse(fileName)
resolveDocumentInheritances(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()
#XML tree composition. Returns the resulting tree, but happens in-place in the overriding tree.
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 #TODO: this will probably cause a bug since it isn't in-place on
#overridingTree
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 = DEFAULT_OVERRIDE_MODE
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 pullArgsFromItem(parentNode):
attribArgs = {}
for arg in parentNode.attrib: #automatically pull attributes into the argdict
attribArgs[arg] = parentNode.attrib[arg]
argNode = parentNode.find('Args')
args = generateArgDict(argNode)
for key in attribArgs:
args[key] = attribArgs[key]
return args
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
#In place resolution of document inheritances. Doesn't return anything.
def resolveDocumentInheritances(el):
abstractMembers = Search.parental_tree_search(el, '.getchildren()', '.tag==\'InheritsFrom\'')
for subel in abstractMembers:
subel = resolveInheritance(subel)
#In place resolution of inheritence. Doesn't return anything.
def resolveInheritance(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(parentTree, el)
el.remove(parentClass) #get rid of the inheritance flag
|