def append(self, something): # We don't want anything but ReportItems if not isinstance(something, ReportItem): list.append(self, something) # This is where we'll implement our logic for deciding whether or not # two reports refer to the same issue. # They must be in the same source file if self.sourcefile != other.sourcefile: # They have to have to be of the same type if self.type != other.type: # They should have the same path length if len(self) != len(other): # Compare each item in the reports for i in range(0, len(self)): # The lines should be within (drumroll for magic number) if abs(self[i].line - other[i].line) > 20: # The comments should be the same, line numbers notwithstanding commentA = re.sub("line [0-9]+", "xxx", self[i].comment) commentB = re.sub("line [0-9]+", "xxx", other[i].comment) # If we don't define this, we can have the case that a == b and a != b return not self.__eq__(other) # This needs to be expanded, for instance to know about the function that class ReportParser(sgmllib.SGMLParser): def __init__(self, pathprefix = ""): sgmllib.SGMLParser.__init__(self) self._pathprefix = pathprefix def handle_comment(self, comment): comment = comment.strip() # We can get BUGFILE and BUGDESC from comments if comment.startswith("BUGFILE"): if bugfile.startswith(self._pathprefix): bugfile = bugfile[len(self._pathprefix) + 1:] self.report.sourcefile = bugfile elif comment.startswith("BUGDESC"): self.report.type = comment[8:].lower() def start_td(self, attrs): if "class" in attrs and attrs["class"] == "num" and \
"id" in attrs and attrs["id"][:2] == "LN": linenum = int(attrs["id"][2:]) # Add a report if we're ready while len(self._queue) > 0: ri.comment = self._queue.pop(0) self.report.endpathline = linenum def start_div(self, attrs): if "class" in attrs and attrs["class"] == "msg": if "id" in attrs and attrs["id"] == "EndPath": self._queue.append(self._buffer) def handle_data(self, data): def summaryPlistForReports(reports, revision = "Unknown"): "Timestamp" : datetime.datetime.utcnow(), "Revision" : str(revision), summary["Reports"].append({ "Report File" : r.reportfile, "Source File" : r.sourcefile, "End Path Line Number" : r.endpathline, summary["Reports"][-1]["Path"].append({ return plistlib.writePlistToString(summary) def summaryPlistToReports(data): summary = plistlib.readPlistFromString(data) for x in summary["Reports"]: report.type = x["Bug Type"] report.reportfile = x["Report File"] report.sourcefile = x["Source File"] report.endpathline = x["End Path Line Number"] item.line = y["Line Number"] item.comment = y["Comment"] if __name__ == "__main__": print "This file should not be invoked directly."