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
0008
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
0028 rxml, nxml = f.read(), ''
0029 q1,q2 = 0,0
0030 for c in rxml :
0031 if (q1 or q2) and c == '<' : nxml += '<'
0032 elif (q1 or q2) and c == '>' : nxml += '>'
0033
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
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
0093 import ROOT
0094 ROOT.PyConfig.DisableRootLogon = True
0095
0096
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
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
0129 if version != classVersion:
0130 return (errorRootDoesNotMatchClassDef,classVersion,classChecksum)
0131
0132
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)