Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-28 22:48:28

0001 class XmlParser(object):
0002     """Parses a classes_def.xml file looking for class declarations that contain
0003     ClassVersion attributes. Once found looks for sub-elements named 'version'
0004     which contain the ClassVersion to checksum mappings.
0005     """
0006     
0007     #The following are constants used to describe what data is kept
0008     # in which index in the 'classes' member data
0009     originalNameIndex=0
0010     classVersionIndex=1
0011     versionsToChecksumIndex = 2
0012     
0013     def __init__(self, filename, includeNonVersionedClasses=False, normalizeClassNames=True):
0014         self._file = filename
0015         self.classes = dict()
0016         self._presentClass = None
0017         self._presentClassForVersion = None
0018         self._includeNonVersionedClasses = includeNonVersionedClasses
0019         self._normalizeClassNames = normalizeClassNames
0020         self.readClassesDefXML()
0021     def readClassesDefXML(self):
0022         import xml.parsers.expat
0023         p = xml.parsers.expat.ParserCreate()
0024         p.StartElementHandler = self.start_element
0025         p.EndElementHandler = self.end_element
0026         f = open(self._file)
0027         # Replace any occurence of <>& in the attribute values by the xml parameter
0028         rxml, nxml = f.read(), ''
0029         q1,q2 = 0,0
0030         for c in rxml :
0031             if   (q1 or q2) and c == '<' : nxml += '&lt;'
0032             elif (q1 or q2) and c == '>' : nxml += '&gt;'
0033             # elif (q1 or q2) and c == '&' : nxml += '&amp;'
0034             else                         : nxml += c
0035             if c == '"' : q1 = not q1
0036             if c == "'" : q2 = not q2
0037         try : p.Parse(nxml)
0038         except xml.parsers.expat.ExpatError as e :
0039             print ('--->> edmCheckClassVersion: ERROR: parsing selection file ',self._file)
0040             print ('--->> edmCheckClassVersion: ERROR: Error is:', e)
0041             raise
0042         f.close()
0043     def start_element(self,name,attrs):
0044         if name in ('class','struct'):
0045             if 'name' in attrs:
0046                 self._presentClass=attrs['name']
0047                 normalizedName = self.genNName(attrs['name'])
0048                 if 'ClassVersion' in attrs:
0049                     self.classes[normalizedName]=[attrs['name'],int(attrs['ClassVersion']),[]]
0050                     self._presentClassForVersion=normalizedName
0051                 elif self._includeNonVersionedClasses:
0052                     # skip transient data products
0053                     if not ('persistent' in attrs and attrs['persistent'] == "false"):
0054                         self.classes[normalizedName]=[attrs['name'],-1,[]]
0055             else:
0056                 raise RuntimeError(f"There is an element '{name}' without 'name' attribute.")
0057         if name == 'version':
0058             if self._presentClassForVersion is None:
0059                 raise RuntimeError(f"Class element for type '{self._presentClass}' contains a 'version' element, but 'ClassVersion' attribute is missing from the 'class' element")
0060             try:
0061                 classVersion = int(attrs['ClassVersion'])
0062             except KeyError:
0063                 raise RuntimeError(f"Version element for type '{self._presentClass}' is missing 'ClassVersion' attribute")
0064             try:
0065                 checksum = int(attrs['checksum'])
0066             except KeyError:
0067                 raise RuntimeError(f"Version element for type '{self._presentClass}' is missing 'checksum' attribute")
0068             self.classes[self._presentClassForVersion][XmlParser.versionsToChecksumIndex].append([classVersion, checksum])
0069         pass
0070     def end_element(self,name):
0071         if name in ('class','struct'):
0072             self._presentClass = None
0073             self._presentClassForVersion = None
0074     def genNName(self, name ):
0075         if not self._normalizeClassNames:
0076             return name
0077         n_name = " ".join(name.split())
0078         for e in [ ['long long unsigned int', 'unsigned long long'],
0079                    ['long long int',          'long long'],
0080                    ['unsigned short int',     'unsigned short'],
0081                    ['short unsigned int',     'unsigned short'],
0082                    ['short int',              'short'],
0083                    ['long unsigned int',      'unsigned long'],
0084                    ['unsigned long int',      'unsigned long'],
0085                    ['long int',               'long'],
0086                    ['std::string',            'std::basic_string<char>']] :
0087             n_name = n_name.replace(e[0],e[1])
0088         n_name = n_name.replace(' ','')
0089         return n_name
0090 
0091 def initROOT(library):
0092     #Need to not have ROOT load .rootlogon.(C|py) since it can cause interference.
0093     import ROOT
0094     ROOT.PyConfig.DisableRootLogon = True
0095 
0096     #Keep ROOT from trying to use X11
0097     ROOT.gROOT.SetBatch(True)
0098     ROOT.gROOT.ProcessLine(".autodict")
0099     if library is not None:
0100         if ROOT.gSystem.Load(library) < 0 :
0101             raise RuntimeError("failed to load library '"+library+"'")
0102 
0103 def initCheckClass():
0104     """Must be called before checkClass()"""
0105     import ROOT
0106     ROOT.gROOT.ProcessLine("class checkclass {public: int f(char const* name) {TClass* cl = TClass::GetClass(name); bool b = false; cl->GetCheckSum(b); return (int)b;} };")
0107     ROOT.gROOT.ProcessLine("checkclass checkTheClass;")
0108 
0109     
0110 #The following are error codes returned from checkClass
0111 noError = 0
0112 errorRootDoesNotMatchClassDef =1
0113 errorMustUpdateClassVersion=2
0114 errorMustAddChecksum=3
0115 
0116 def checkClass(name,version,versionsToChecksums):
0117     import ROOT
0118     c = ROOT.TClass.GetClass(name)
0119     if not c:
0120         raise RuntimeError("failed to load dictionary for class '"+name+"'")
0121     temp = "checkTheClass.f(" + '"' + name + '"' + ");"
0122     retval = ROOT.gROOT.ProcessLine(temp)
0123     if retval == 0 :
0124         raise RuntimeError("TClass::GetCheckSum: Failed to load dictionary for base class. See previous Error message")
0125     classChecksum = c.GetCheckSum()
0126     classVersion = c.GetClassVersion()
0127 
0128     #does this version match what is in the file?
0129     if version != classVersion:
0130         return (errorRootDoesNotMatchClassDef,classVersion,classChecksum)
0131 
0132     #is the version already in our list?
0133     found = False
0134     
0135     for v,cs in versionsToChecksums:
0136         if v == version:
0137             found = True
0138             if classChecksum != cs:
0139                 return (errorMustUpdateClassVersion,classVersion,classChecksum)
0140             break
0141     if not found and classVersion != 0:
0142         return (errorMustAddChecksum,classVersion,classChecksum)
0143     return (noError,classVersion,classChecksum)