--- a/sbsv2/raptor/python/filter_interface.py Tue Nov 02 16:54:53 2010 +0800
+++ b/sbsv2/raptor/python/filter_interface.py Fri Nov 12 14:49:36 2010 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of the License "Eclipse Public License v1.0"
@@ -36,6 +36,53 @@
def formatWarning(self, message):
return "sbs: warning: " + message + "\n"
+ def parseNamedParams(self, names, params):
+ ''' Match named parameters e.g. ['a=b','c=d'] against a list of expected
+ names. Allow for abbreviations.
+ '''
+ r = {}
+
+ # Shorten all the names so they match abbreviations
+ shortnames = []
+
+ for name in names:
+ shortname = ""
+ conflict = True
+ while len(shortname)<len(name) and conflict:
+ shortname+=name[len(shortname)]
+ conflict = False
+ othernames = names[:] # Copy
+ othernames.remove(name)
+ for othername in othernames:
+ if othername.startswith(shortname):
+ conflict = True
+ break
+ if conflict == False:
+ shortnames.append((shortname,name))
+ r[name] = [] # Prime the hash key for this param
+ if conflict:
+ raise KeyError("Parameter name '{0}' duplicated".format(name))
+
+ # Parse the params
+ for param in params:
+ if '=' in param:
+ (key,value) = param.split('=')
+ matched = False
+ for (shortname, name) in shortnames:
+ if key.strip().startswith(shortname):
+ r[name].append(value.strip())
+ matched = True
+ break
+ if not matched:
+ raise ValueError("Named parameter '{0}' not valid in filter {1}".format(key,self.__class__.__name__))
+ else:
+ # Unnamed arg
+ if not '' in names:
+ raise ValueError("All parameters to the {0} filter must be named".format(self.__class__.__name__))
+ else:
+ r[''].append(param.strip())
+ return r
+
import sys
import xml.sax
@@ -82,29 +129,20 @@
"initialise"
self.params = params
+
+ self.parser = xml.sax.make_parser(['xml.sax.expatreader'])
+ self.parser.setContentHandler(self)
+ self.parser.setErrorHandler(self)
+
self.ok = True
- try:
- self.parser = xml.sax.make_parser(['xml.sax.expatreader'])
- self.parser.setContentHandler(self)
- self.parser.setErrorHandler(self)
+
+ return self.ok
- except Exception, ex:
- sys.stderr.write(self.formatError(str(ex)))
- self.ok = False
-
- return self.ok
-
-
def write(self, text):
"process some log text"
- try:
+ if self.ok:
self.parser.feed(text)
- except Exception, ex:
- sys.stderr.write(self.formatError(str(ex)))
- self.ok = False
-
return self.ok
-
def close(self):
"finish off"
@@ -116,5 +154,107 @@
return self.ok
+class RaptorLogNotValid(Exception):
+ pass
+
+class PerRecipeFilter(FilterSAX):
+ # Define this in your class
+ def handleRecipe(self):
+ # These variables are available to you:
+ # self.name
+ # self.target
+ # self.host
+ # self.layer
+ # self.component
+ # self.bldinf
+ # self.mmp
+ # self.config
+ # self.platform
+ # self.phase
+ # self.source
+ # self.prereqs
+ # self.text
+ # self.exit
+ # self.attempt (final attempt number)
+ # self.flags
+ # self.start
+ # self.elapsed
+
+ return False
+
+ # Helper functions
+ def formatData(self, key, hash='self'):
+ '''Output prettifier - return the attribute value, or just return 'undef' if the attribute is not set.'''
+
+ if hash=='self':
+ hash=self.__dict__
+ if hash.has_key(key):
+ return hash[key]
+ else:
+ return 'undef'
+
+ # data keys
+ recipeData = set(['name','target','host','layer','component','bldinf','mmp','config','platform','phase','source','prereqs'])
+ statusData = set(['exit','attempt','flags'])
+ timeData = set(['start','elapsed'])
+
+ # methods from the SAX parser
+ def startDocument(self):
+ self.inRecipe = False
+ self.text = ""
+
+ def startElement(self, name, attributes):
+ if name == "recipe":
+ if self.inRecipe:
+ self.error(RaptorLogNotValid("Nested recipes; {0} recipe for {1} inside {2} recipe for {3}".format(self.formatData('name', hash=attributes), self.formatData('target',hash=attributes), self.formatData('name'), self.formatData('target') )))
+ else:
+ self.inRecipe = True
+ self.__setHashElements(attributes, self.__dict__, self.recipeData )
+ elif self.inRecipe:
+ if name == "status":
+ self.__setHashElements(attributes, self.__dict__, self.statusData)
+ elif name == "time":
+ self.__setHashElements(attributes, self.__dict__, self.timeData)
+ else:
+ self.error(RaptorLogNotValid("Unexpected <{0}> tag in {1} recipe for {2}".format(name, self.formatData('name'), self.formatData('target'))))
+
+ def endElement(self, name):
+ if name == "recipe":
+ if not self.inRecipe:
+ self.error(RaptorLogNotValid("Extra recipe close tag"))
+ else:
+ if not self.handleRecipe():
+ self.error(RaptorLogNotValid('Handling of {0} recipe for {1} failed'.format(self.formatData('name'), self.formatData('target'))))
+ self.inRecipe = False
+
+ self.__delData(self.recipeData|self.statusData|self.timeData)
+ self.text=""
+
+ def characters(self, char):
+ if self.inRecipe:
+ self.text += char
+
+ def error(self, exception):
+ "the parse found an error which is (possibly) recoverable"
+ pass
+
+ def fatalError(self, exception):
+ "the parser thinks an error occurred which should stop everything"
+ pass
+
+ def warning(self, exception):
+ "the parser found something to complain about that might not matter"
+ pass
+
+ # Private methods
+ def __setHashElements(self, fro, to, keys):
+ for key in keys:
+ if fro.has_key(key):
+ to[key] = fro[key]
+
+ def __delData(self, keys):
+ for key in keys:
+ if self.__dict__.has_key(key):
+ del self.__dict__[key]
# the end