7 from xml.dom
import minidom
11 from cPickle
import load, dump
12 from hashlib
import md5
15 '''Takes care of XML file operations such as reading and writing.'''
18 self.
xmlResult =
'<?xml version="1.0" encoding="UTF-8"?><env:config xmlns:env="EnvSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="EnvSchema ./EnvSchema.xsd ">\n'
20 logConf = os.path.normpath(os.path.dirname(os.path.realpath(__file__)) +
'/log.conf')
21 if not logging.getLogger(
'envLogger').handlers
and os.path.exists(logConf):
22 logging.config.fileConfig(logConf)
23 self.
logger = logging.getLogger(
'envLogger')
25 def variable(self, path, namespace='EnvSchema', name=None):
26 '''Returns list containing name of variable, action and value.
28 @param path: a file name or a file-like object
30 If no name given, returns list of lists of all variables and locals(instead of action 'local' is filled).
32 isFilename =
type(path)
is str
35 checksum.update(open(path,
'rb').read())
36 checksum = checksum.digest()
41 oldsum, data = load(f)
42 if oldsum == checksum:
54 doc = minidom.parse(path)
58 ELEMENT_NODE = minidom.Node.ELEMENT_NODE
60 nodes = doc.getElementsByTagNameNS(namespace,
"config")[0].childNodes
64 if node.nodeType == ELEMENT_NODE:
65 action = str(node.localName)
67 if action ==
'include':
69 value = str(node.childNodes[0].data)
72 variables.append((action, (value, caller, str(node.getAttribute(
'hints')))))
75 varname = str(node.getAttribute(
'variable'))
76 if name
and varname != name:
79 if action ==
'declare':
80 variables.append((action, (varname, str(node.getAttribute(
'type')), str(node.getAttribute(
'local')))))
83 value = str(node.childNodes[0].data)
86 variables.append((action, (varname, value,
None)))
91 dump((checksum, variables), f, protocol=2)
99 '''resets the buffer of writer'''
100 self.
xmlResult =
'<?xml version="1.0" encoding="UTF-8"?><env:config xmlns:env="EnvSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="EnvSchema ./EnvSchema.xsd ">\n'
104 '''Finishes the XML input and writes XML to file.'''
105 if outputFile
is None:
106 raise IOError(
"No output file given")
109 doc = minidom.parseString(self.
xmlResult)
110 with open(outputFile,
"w")
as f:
111 f.write( doc.toxml() )
116 def writeVar(self, varName, action, value, vartype='list', local=False):
117 '''Writes a action to a file. Declare undeclared elements (non-local list is default type).'''
118 if action ==
'declare':
119 self.
xmlResult +=
'<env:declare variable="'+varName+
'" type="'+ vartype.lower() +
'" local="'+(str(local)).lower()+
'" />\n'
120 self.declaredVars.append(varName)
124 self.
xmlResult +=
'<env:declare variable="'+varName+
'" type="'+ vartype +
'" local="'+(str(local)).lower()+
'" />\n'
125 self.declaredVars.append(varName)
126 self.
xmlResult +=
'<env:'+action+
' variable="'+ varName +
'">'+value+
'</env:'+action+
'>\n'
130 '''This class is used to catch errors and warnings from XML file processing to allow better managing and testing.'''
133 def __init__(self, level = 1, reportOutput = False):
145 logConf = os.path.normpath(os.path.dirname(os.path.realpath(__file__)) +
'/log.conf')
146 if not logging.getLogger(
'envLogger').handlers
and os.path.exists(logConf):
147 logging.config.fileConfig(logConf)
148 self.
logger = logging.getLogger(
'envLogger')
150 def addError(self, message, varName = '', action = '', varValue = '', procedure = ''):
151 error = [message, varName, action, varValue, procedure]
154 print 'Error: ' + error[0]
156 self.reportOutput.write(
'Error: ' + error[0] +
'\n')
157 self.errors.append(error)
158 self.logger.error(message)
160 def addWarn(self, message, varName = '', action = '', varValue = '', procedure = ''):
161 error = [message, varName, action, varValue, procedure]
164 print 'Warn: ' + error[0]
166 self.reportOutput.write(
'Warn: ' + error[0] +
'\n')
167 self.warns.append(error)
168 self.logger.warn(message)
170 def addWarning(self, message, varName = '', action = '', varValue = '', procedure = ''):
171 error = [message, varName, action, varValue, procedure]
174 print 'Warning: ' + error[0]
176 self.reportOutput.write(
'Warning: ' + error[0] +
'\n')
177 self.warnings.append(error)
178 self.logger.warning(message)
180 def addInfo(self, message, varName = '', action = '', varValue = '', procedure = ''):
181 error = [message, varName, action, varValue, procedure]
184 print 'Info: ' + error[0]
186 self.reportOutput.write(
'Info: ' + error[0] +
'\n')
187 self.warnings.append(error)
188 self.logger.info(message)
198 self.reportOutput.close()
210 return self.
warns[key]
214 '''This class is for checking and merging XML files.
216 Variables are stored in a double dictionary with keys of names and then actions.
218 def __init__(self, separator=':
', reportLevel=0, reportOutput=None):
219 self.posActions = ['append',
'prepend',
'set',
'unset',
'remove',
'remove-regexp',
'declare']
229 return self.report.numErrors()
232 return self.report.numWarnings()
235 '''Runs a check through file
237 First check is made on wrong action parameter.
238 All valid actions are checked after and duplicated variables as well.
251 self.report.addInfo(
'Encountered '+ (str)(self.
warnings()) +
' warnings and ' + (str)(self.
errors()) +
' errors.')
256 self.report.closeFile()
259 def merge(self, xmlDoc1, xmlDoc2, outputFile = '', reportCheck = False):
260 '''Merges two files together. Files are checked first during variables loading process.
262 Second file is processed first, then the first file and after that they are merged together.
268 variables = self.file.variable(xmlDoc1)
270 variables = self.file.variable(xmlDoc2)
274 self.report.level = 5
276 self.file.writeToFile(outputFile)
278 self.report.addInfo(
'Files merged. Running check on the result.')
280 self.report.closeFile()
283 for action, (arg1, arg2, arg3)
in variables:
284 if action ==
'declare':
285 if arg1
in self.variables.keys():
286 if arg2.lower() != self.
variables[arg1][0]:
289 if arg3.lower() != self.
variables[arg1][1]:
292 self.file.writeVar(arg1,
'declare',
'', arg2, arg3)
293 self.
variables[arg1] = [arg2.lower(), arg3.lower()]
295 self.file.writeVar(arg1, action, arg2)
299 '''Tries to add to variables dict, checks for errors during process'''
306 elif action ==
'unset':
308 self.report.addWarn(
'Multiple "unset" actions found for variable: "'+varName+
'".', varName,
'multiple unset',
'',
'checkVariable')
310 self.report.addError(
'Node '+str(nodeNum)+
': "unset" action found for variable "'+varName+
'" after previous command(s). Any previous commands are overridden.', varName,
'unset overwrite')
313 elif action ==
'set':
315 self.report.addWarn(
'Node '+str(nodeNum)+
': "set" action found for variable "'+varName+
'" after unset. Can be merged to one set only.')
317 self.report.addError(
'Node '+str(nodeNum)+
': "set" action found for variable "'+varName+
'" after previous command(s). Any previous commands are overridden.', varName,
'set overwrite')
319 self.report.addWarn(
'Multiple "set" actions found for variable: "'+varName+
'".', varName,
'multiple set',
'',
'checkVariable')
321 if action
not in self.
variables[varName]:
325 if action ==
'remove-regexp':
326 action =
'remove_regexp'
327 eval(
'(self.realVariables[varName]).'+action+
'(value)')
329 if e.code ==
'undefined':
330 self.report.addWarn(
'Referenced variable "' +e.val+
'" is not defined.')
331 elif e.code ==
'ref2var':
332 self.report.addError(
'Reference to list from the middle of string.')
333 elif e.code ==
'redeclaration':
334 self.report.addError(
'Redeclaration of variable "'+e.val+
'".')
336 self.report.addError(
'Unknown environment error occured.')
340 '''loads XML file for input variables'''
342 variables = XMLfile.variable(fileName)
343 for i, (action, (arg1, arg2, arg3))
in enumerate(variables):
346 raise RuntimeError(
'Empty variable or local name is not allowed.')
348 if arg1
not in self.realVariables.keys():
349 if action !=
'declare':
350 self.report.addInfo(
'Node '+str(i)+
': Variable '+arg1+
' is used before declaration. Treated as an unlocal list furthermore.')
354 self.varNames.append(arg1)
363 self.report.addError(
'Node '+str(i)+
': Action "'+action+
'" which is not implemented found. Variable "'+arg1+
'".', arg1, action, arg2)
367 if action ==
'declare':
368 self.report.addError(
'Node '+str(i)+
': Variable '+arg1+
' is redeclared.')