Package SmootLight :: Package util :: Module Config
[hide private]
[frames] | no frames]

Source Code for Module SmootLight.util.Config

  1  from xml.etree.ElementTree import * 
  2  import re 
  3  import sys 
  4  import xml 
  5  import pdb 
  6  import util.Strings as Strings 
  7  import util.Search as Search 
  8  from logger import main_log, exception_log 
  9  classArgsMem = {} 
 10  CONFIG_PATH = 'config/' 
 11  DEFAULT_OVERRIDE_MODE = 'Merge' 
 12   
13 -def loadParamRequirementDict(className):
14 if not className in classArgsMem: #WOO CACHING 15 classArgsMem[className] = fileToDict(CONFIG_PATH + className) 16 return classArgsMem[className]
17
18 -def loadConfigFile(fileName): #TODO: error handling etc.
19 """Loads a config file. If its an xml file, inheritances are automatically resolved.""" 20 try: 21 if '.params' in fileName: 22 return fileToDict(fileName) 23 if '.xml' in fileName: 24 config = ElementTree() 25 config.parse(fileName) 26 resolveDocumentInheritances(config.getroot()) 27 return config 28 except Exception as inst: 29 main_log.info('Error loading config file ' + fileName)#, inst) TODO: log exception too 30 main_log.info(str(inst)) 31 return None
32 -def getElement(el):
33 """Takes an Element or an ElementTree. If it is a tree, it returns its root. Otherwise, just returns 34 it""" 35 if xml.etree.ElementTree.iselement(el): 36 return el 37 elif el.__class__ == ElementTree: 38 return el.getroot()
39 -def compositeXMLTrees(parentTree, overridingTree):
40 """XML tree composition. Returns the resulting tree, but happens in-place in the overriding 41 tree.""" 42 #TODO: break up into sub-methods, change it to use .find() 43 if parentTree == None: 44 return overridingTree 45 if overridingTree == None: 46 return parentTree #TODO: this will probably cause a bug since it isn't in-place on 47 #overridingTree 48 parentTree = getElement(parentTree) 49 overridingTree = getElement(overridingTree) 50 parentItems = parentTree.getchildren() 51 overrideItems = overridingTree.getchildren() 52 #first, lets figure out what tags we have in the override tree: 53 tagCollection = [el.tag for el in overrideItems] #we can speed this up with a dict if necessary 54 for item in parentItems: 55 if not item.tag in tagCollection: #no override 56 overridingTree.insert(-1, item) #insert the new item at the end 57 else: 58 #do we merge or replace? 59 intersectingElements = findElementsByTag(item.tag, overrideItems) 60 if len(intersectingElements) > 1: 61 main_log.warn('ABUSE! Override of multiple items isn\'t well defined. Don\'t do\ 62 it!') 63 interEl = intersectingElements[0] 64 mode = DEFAULT_OVERRIDE_MODE 65 if Strings.OVERRIDE_BEHAVIOR in interEl.attrib: 66 mode = interEl.attrib[Strings.OVERRIDE_BEHAVIOR] 67 if mode != 'Replace' and mode != 'Merge': 68 main_log.warn('Bad Override Mode. Choosing to replace.') 69 mode = 'Replace' 70 if mode == 'Replace': 71 pass #we don't need to do anything 72 if mode == 'Merge': 73 interEl = compositeXMLTrees(item, interEl) 74 for item in overrideItems: #resolve appendages 75 if item.tag == 'APPEND': 76 children = item.getchildren() 77 for child in children: 78 overrideItems.insert(-1, child) 79 overrideItems.remove(item) 80 return overridingTree 81
82 -def findElementsByTag(tag, eList):
83 return [el for el in eList if el.tag == tag]
84
85 -def fileToDict(fileName):
86 fileText = '' 87 try: 88 with open(fileName) as f: 89 for line in f: 90 fileText += line.rstrip('\n').lstrip('\t') + ' ' 91 except IOError: 92 main_log.info('Failure reading ' + fileName) 93 return {} 94 if fileText == '': 95 return {} 96 try: 97 resultDict = eval(fileText) 98 main_log.info(fileName + ' read and parsed') 99 return resultDict 100 except: 101 main_log.exception(fileName + ' is not a well formed python dict. Parsing failed') 102 return eval(fileText)
103
104 -def pullArgsFromItem(parentNode):
105 """Parses arguments into python objects if possible, otherwise leaves as strings""" 106 attribArgs = {} 107 for arg in parentNode.attrib: #automatically pull attributes into the argdict 108 attribArgs[arg] = attemptEval(parentNode.attrib[arg]) 109 argNode = parentNode.find('Args') 110 args = generateArgDict(argNode) 111 for key in attribArgs: 112 args[key] = attribArgs[key] 113 return args
114
115 -def attemptEval(val):
116 """Runs an eval if possible, or converts into a lambda expression if indicated. Otherwise, 117 leaves as a string.""" 118 try: 119 if '${' in val and '}$' in val: #TODO: this could be a little cleaner 120 dictVal = re.sub("'\$\{(.+?)\}\$'", "b['\\1']", val) #replace expressions '${blah}$' with b['blah'] 121 dictVal = re.sub("\$\{(.+?)\}\$", "a['\\1']", dictVal) #replace all expressions like {blah} with a['blah'] 122 if "'${" and "}$'" in val: #nested lambda madness 123 lambdaVal = eval('lambda a: lambda b: ' + dictVal) 124 else: 125 lambdaVal = eval('lambda a:'+dictVal) #TODO: nested lambdas 126 return lambdaVal #convert referential objects to lambda expressions which can be 127 #resolved dynamically. 128 else: 129 val = eval(val) 130 except (NameError, SyntaxError): 131 val = str(val) 132 return val
133
134 -def generateArgDict(parentNode, recurse=False):
135 args = {} 136 for arg in parentNode.getchildren(): 137 key = arg.tag 138 if arg.getchildren() != []: 139 value = generateArgDict(arg, True) 140 else: 141 #convert into python if possible, otherwise don't 142 value = attemptEval(arg.text) 143 if key in args: #build of lists of like-elements 144 if type(args[key]) != type([]): 145 args[key] = [args[key]] 146 args[key].append(value) 147 else: 148 args[key]=value 149 #if we should be a list but we aren't: 150 if len(args.keys()) == 1 and recurse: 151 return args[args.keys()[0]] 152 return args
153 -def resolveDocumentInheritances(el):
154 """In place resolution of document inheritances. Doesn't return anything.""" 155 abstractMembers = Search.parental_tree_search(el, '.getchildren()', '.tag==\'InheritsFrom\'') 156 for subel in abstractMembers: 157 subel = resolveInheritance(subel)
158 -def resolveInheritance(el):
159 """In place resolution of inheritence. Doesn't return anything.""" 160 parentClass = el.find('InheritsFrom') 161 if parentClass != None: 162 parentTree = loadConfigFile(parentClass.text) 163 if parentTree == None: 164 main_log.warn('Inheritance Failed. ' + parentClass.text + 'does not exist') 165 main_log.error('Inheritance Failed. ' + parentClass.text + 'does not exist') 166 return el 167 el = compositeXMLTrees(parentTree, el) 168 el.remove(parentClass) #get rid of the inheritance flag
169