def __init__(self, a, b, highlighter, callNos=False): self.a = a self.b = b self.highlighter = highlighter self.delete_color = highlighter.red self.insert_color = highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper()
def __init__(self, apitrace, callNos=False): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper()
def __init__(self, apitrace, options): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = options.callNos self.suppressCommonLines = options.suppressCommonLines self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper()
def __init__(self, a, b, highlighter, callNos = False): self.a = a self.b = b self.highlighter = highlighter self.delete_color = highlighter.red self.insert_color = highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper()
def __init__(self, apitrace, callNos = False): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper()
class SDiffer: def __init__(self, a, b, highlighter, callNos=False): self.a = a self.b = b self.highlighter = highlighter self.delete_color = highlighter.red self.insert_color = highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper() def diff(self): matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b) for tag, alo, ahi, blo, bhi in matcher.get_opcodes(): if tag == 'replace': self.replace(alo, ahi, blo, bhi) elif tag == 'delete': self.delete(alo, ahi, blo, bhi) elif tag == 'insert': self.insert(alo, ahi, blo, bhi) elif tag == 'equal': self.equal(alo, ahi, blo, bhi) else: raise ValueError, 'unknown tag %s' % (tag, ) def isjunk(self, call): return call.functionName == 'glGetError' and call.ret in ( 'GL_NO_ERROR', 0) def replace(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi a_names = [call.functionName for call in self.a[alo:ahi]] b_names = [call.functionName for call in self.b[blo:bhi]] matcher = difflib.SequenceMatcher(None, a_names, b_names) for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes(): _alo += alo _ahi += alo _blo += blo _bhi += blo if tag == 'replace': self.replace_dissimilar(_alo, _ahi, _blo, _bhi) elif tag == 'delete': self.delete(_alo, _ahi, _blo, _bhi) elif tag == 'insert': self.insert(_alo, _ahi, _blo, _bhi) elif tag == 'equal': self.replace_similar(_alo, _ahi, _blo, _bhi) else: raise ValueError, 'unknown tag %s' % (tag, ) def replace_similar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write('| ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName self.dumpCallNos(a_call.no, b_call.no) self.highlighter.bold(True) self.highlighter.write(b_call.functionName) self.highlighter.bold(False) self.highlighter.write('(') sep = '' numArgs = max(len(a_call.args), len(b_call.args)) for j in xrange(numArgs): self.highlighter.write(sep) try: a_arg = a_call.args[j] except IndexError: pass try: b_arg = b_call.args[j] except IndexError: pass self.replace_value(a_arg, b_arg) sep = ', ' self.highlighter.write(')') if a_call.ret is not None or b_call.ret is not None: self.highlighter.write(' = ') self.replace_value(a_call.ret, b_call.ret) self.highlighter.write('\n') def replace_dissimilar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi if bhi - blo < ahi - alo: self.insert(alo, alo, blo, bhi) self.delete(alo, ahi, bhi, bhi) else: self.delete(alo, ahi, blo, blo) self.insert(ahi, ahi, blo, bhi) def replace_value(self, a, b): if b == a: self.highlighter.write(self.dumper.visit(b)) else: self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(self.dumper.visit(a)) self.highlighter.normal() self.highlighter.write(" ") self.highlighter.color(self.insert_color) self.highlighter.write(self.dumper.visit(b)) self.highlighter.normal() escape = "\33[" def delete(self, alo, ahi, blo, bhi): assert alo < ahi assert blo == bhi for i in xrange(alo, ahi): call = self.a[i] self.highlighter.write('- ') self.dumpCallNos(call.no, None) self.highlighter.strike() self.highlighter.color(self.delete_color) self.dumpCall(call) def insert(self, alo, ahi, blo, bhi): assert alo == ahi assert blo < bhi for i in xrange(blo, bhi): call = self.b[i] self.highlighter.write('+ ') self.dumpCallNos(None, call.no) self.highlighter.color(self.insert_color) self.dumpCall(call) def equal(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write(' ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.dumpCall(b_call) def dumpCallNos(self, aNo, bNo): if not self.callNos: return if aNo is None: self.highlighter.write(' ' * self.aSpace) else: aNoStr = str(aNo) self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(aNoStr) self.highlighter.normal() self.aSpace = len(aNoStr) self.highlighter.write(' ') if bNo is None: self.highlighter.write(' ' * self.bSpace) else: bNoStr = str(bNo) self.highlighter.color(self.insert_color) self.highlighter.write(bNoStr) self.highlighter.normal() self.bSpace = len(bNoStr) self.highlighter.write(' ') def dumpCall(self, call): self.highlighter.bold(True) self.highlighter.write(call.functionName) self.highlighter.bold(False) self.highlighter.write( '(' + ', '.join(itertools.imap(self.dumper.visit, call.args)) + ')') if call.ret is not None: self.highlighter.write(' = ' + self.dumper.visit(call.ret)) self.highlighter.normal() self.highlighter.write('\n')
class SDiffer: def __init__(self, a, b, highlighter, callNos = False): self.a = a self.b = b self.highlighter = highlighter self.delete_color = highlighter.red self.insert_color = highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper() def diff(self): matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b) for tag, alo, ahi, blo, bhi in matcher.get_opcodes(): if tag == 'replace': self.replace(alo, ahi, blo, bhi) elif tag == 'delete': self.delete(alo, ahi, blo, bhi) elif tag == 'insert': self.insert(alo, ahi, blo, bhi) elif tag == 'equal': self.equal(alo, ahi, blo, bhi) else: raise ValueError, 'unknown tag %s' % (tag,) def isjunk(self, call): return call.functionName == 'glGetError' and call.ret in ('GL_NO_ERROR', 0) def replace(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi a_names = [call.functionName for call in self.a[alo:ahi]] b_names = [call.functionName for call in self.b[blo:bhi]] matcher = difflib.SequenceMatcher(None, a_names, b_names) for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes(): _alo += alo _ahi += alo _blo += blo _bhi += blo if tag == 'replace': self.replace_dissimilar(_alo, _ahi, _blo, _bhi) elif tag == 'delete': self.delete(_alo, _ahi, _blo, _bhi) elif tag == 'insert': self.insert(_alo, _ahi, _blo, _bhi) elif tag == 'equal': self.replace_similar(_alo, _ahi, _blo, _bhi) else: raise ValueError, 'unknown tag %s' % (tag,) def replace_similar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write('| ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.highlighter.bold(True) self.highlighter.write(b_call.functionName) self.highlighter.bold(False) self.highlighter.write('(') sep = '' for j in xrange(len(b_call.args)): self.highlighter.write(sep) self.replace_value(a_call.args[j], b_call.args[j]) sep = ', ' self.highlighter.write(')') if a_call.ret is not None or b_call.ret is not None: self.highlighter.write(' = ') self.replace_value(a_call.ret, b_call.ret) self.highlighter.write('\n') def replace_dissimilar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi if bhi - blo < ahi - alo: self.insert(alo, alo, blo, bhi) self.delete(alo, ahi, bhi, bhi) else: self.delete(alo, ahi, blo, blo) self.insert(ahi, ahi, blo, bhi) def replace_value(self, a, b): if b == a: self.highlighter.write(self.dumper.visit(b)) else: self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(self.dumper.visit(a)) self.highlighter.normal() self.highlighter.write(" ") self.highlighter.color(self.insert_color) self.highlighter.write(self.dumper.visit(b)) self.highlighter.normal() escape = "\33[" def delete(self, alo, ahi, blo, bhi): assert alo < ahi assert blo == bhi for i in xrange(alo, ahi): call = self.a[i] self.highlighter.write('- ') self.dumpCallNos(call.no, None) self.highlighter.strike() self.highlighter.color(self.delete_color) self.dumpCall(call) def insert(self, alo, ahi, blo, bhi): assert alo == ahi assert blo < bhi for i in xrange(blo, bhi): call = self.b[i] self.highlighter.write('+ ') self.dumpCallNos(None, call.no) self.highlighter.color(self.insert_color) self.dumpCall(call) def equal(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write(' ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.dumpCall(b_call) def dumpCallNos(self, aNo, bNo): if not self.callNos: return if aNo is None: self.highlighter.write(' '*self.aSpace) else: aNoStr = str(aNo) self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(aNoStr) self.highlighter.normal() self.aSpace = len(aNoStr) self.highlighter.write(' ') if bNo is None: self.highlighter.write(' '*self.bSpace) else: bNoStr = str(bNo) self.highlighter.color(self.insert_color) self.highlighter.write(bNoStr) self.highlighter.normal() self.bSpace = len(bNoStr) self.highlighter.write(' ') def dumpCall(self, call): self.highlighter.bold(True) self.highlighter.write(call.functionName) self.highlighter.bold(False) self.highlighter.write('(' + ', '.join(itertools.imap(self.dumper.visit, call.args)) + ')') if call.ret is not None: self.highlighter.write(' = ' + self.dumper.visit(call.ret)) self.highlighter.normal() self.highlighter.write('\n')
class PythonDiffer(Differ): def __init__(self, apitrace, options): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = options.callNos self.suppressCommonLines = options.suppressCommonLines self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper() def setRefTrace(self, refTrace, ref_calls): self.a = self.readTrace(refTrace, ref_calls) def setSrcTrace(self, srcTrace, src_calls): self.b = self.readTrace(srcTrace, src_calls) def readTrace(self, trace, calls): p = subprocess.Popen( args = [ self.apitrace, 'pickle', '--symbolic', '--calls=' + calls, trace ], stdout=subprocess.PIPE, ) parser = Loader(p.stdout) parser.parse() return parser.calls def diff(self): try: self._diff() except IOError: pass def _diff(self): matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b) for tag, alo, ahi, blo, bhi in matcher.get_opcodes(): if tag == 'replace': self.replace(alo, ahi, blo, bhi) elif tag == 'delete': self.delete(alo, ahi, blo, bhi) elif tag == 'insert': self.insert(alo, ahi, blo, bhi) elif tag == 'equal': self.equal(alo, ahi, blo, bhi) else: raise ValueError('unknown tag %s' % (tag,)) def isjunk(self, call): return call.functionName == 'glGetError' and call.ret in ('GL_NO_ERROR', 0) def replace(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi a_names = [call.functionName for call in self.a[alo:ahi]] b_names = [call.functionName for call in self.b[blo:bhi]] matcher = difflib.SequenceMatcher(None, a_names, b_names) for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes(): _alo += alo _ahi += alo _blo += blo _bhi += blo if tag == 'replace': self.replace_dissimilar(_alo, _ahi, _blo, _bhi) elif tag == 'delete': self.delete(_alo, _ahi, _blo, _bhi) elif tag == 'insert': self.insert(_alo, _ahi, _blo, _bhi) elif tag == 'equal': self.replace_similar(_alo, _ahi, _blo, _bhi) else: raise ValueError('unknown tag %s' % (tag,)) def replace_similar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in range(0, bhi - blo): self.highlighter.write('| ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName self.dumpCallNos(a_call.no, b_call.no) self.highlighter.bold(True) self.highlighter.write(b_call.functionName) self.highlighter.bold(False) self.highlighter.write('(') sep = '' numArgs = max(len(a_call.args), len(b_call.args)) for j in range(numArgs): self.highlighter.write(sep) try: a_argName, a_argVal = a_call.args[j] except IndexError: pass try: b_argName, b_argVal = b_call.args[j] except IndexError: pass self.replace_value(a_argName, b_argName) self.highlighter.write(' = ') self.replace_value(a_argVal, b_argVal) sep = ', ' self.highlighter.write(')') if a_call.ret is not None or b_call.ret is not None: self.highlighter.write(' = ') self.replace_value(a_call.ret, b_call.ret) self.highlighter.write('\n') def replace_dissimilar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi if bhi - blo < ahi - alo: self.insert(alo, alo, blo, bhi) self.delete(alo, ahi, bhi, bhi) else: self.delete(alo, ahi, blo, blo) self.insert(ahi, ahi, blo, bhi) def replace_value(self, a, b): if b == a: self.highlighter.write(self.dumper.visit(b)) else: self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(self.dumper.visit(a)) self.highlighter.normal() self.highlighter.write(" -> ") self.highlighter.color(self.insert_color) self.highlighter.write(self.dumper.visit(b)) self.highlighter.normal() escape = "\33[" def delete(self, alo, ahi, blo, bhi): assert alo < ahi assert blo == bhi for i in range(alo, ahi): call = self.a[i] self.highlighter.write('- ') self.dumpCallNos(call.no, None) self.highlighter.strike() self.highlighter.color(self.delete_color) self.dumpCall(call) def insert(self, alo, ahi, blo, bhi): assert alo == ahi assert blo < bhi for i in range(blo, bhi): call = self.b[i] self.highlighter.write('+ ') self.dumpCallNos(None, call.no) self.highlighter.color(self.insert_color) self.dumpCall(call) def equal(self, alo, ahi, blo, bhi): if self.suppressCommonLines: return assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in range(0, bhi - blo): self.highlighter.write(' ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.dumpCall(b_call) def dumpCallNos(self, aNo, bNo): if not self.callNos: return if aNo is not None and bNo is not None and aNo == bNo: aNoStr = str(aNo) self.highlighter.write(aNoStr) self.aSpace = len(aNoStr) self.bSpace = self.aSpace self.highlighter.write(' ') return if aNo is None: self.highlighter.write(' '*self.aSpace) else: aNoStr = str(aNo) self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(aNoStr) self.highlighter.normal() self.aSpace = len(aNoStr) self.highlighter.write(' ') if bNo is None: self.highlighter.write(' '*self.bSpace) else: bNoStr = str(bNo) self.highlighter.color(self.insert_color) self.highlighter.write(bNoStr) self.highlighter.normal() self.bSpace = len(bNoStr) self.highlighter.write(' ') def dumpCall(self, call): self.highlighter.bold(True) self.highlighter.write(call.functionName) self.highlighter.bold(False) self.highlighter.write('(' + self.dumper.visitItems(call.args) + ')') if call.ret is not None: self.highlighter.write(' = ' + self.dumper.visit(call.ret)) self.highlighter.normal() self.highlighter.write('\n')
class PythonDiffer(Differ): def __init__(self, apitrace, options): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = options.callNos self.suppressCommonLines = options.suppressCommonLines self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper() def setRefTrace(self, refTrace, ref_calls): self.a = self.readTrace(refTrace, ref_calls) def setSrcTrace(self, srcTrace, src_calls): self.b = self.readTrace(srcTrace, src_calls) def readTrace(self, trace, calls): p = subprocess.Popen( args=[self.apitrace, "pickle", "--symbolic", "--calls=" + calls, trace], stdout=subprocess.PIPE ) parser = Loader(p.stdout) parser.parse() return parser.calls def diff(self): try: self._diff() except IOError: pass def _diff(self): matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b) for tag, alo, ahi, blo, bhi in matcher.get_opcodes(): if tag == "replace": self.replace(alo, ahi, blo, bhi) elif tag == "delete": self.delete(alo, ahi, blo, bhi) elif tag == "insert": self.insert(alo, ahi, blo, bhi) elif tag == "equal": self.equal(alo, ahi, blo, bhi) else: raise ValueError, "unknown tag %s" % (tag,) def isjunk(self, call): return call.functionName == "glGetError" and call.ret in ("GL_NO_ERROR", 0) def replace(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi a_names = [call.functionName for call in self.a[alo:ahi]] b_names = [call.functionName for call in self.b[blo:bhi]] matcher = difflib.SequenceMatcher(None, a_names, b_names) for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes(): _alo += alo _ahi += alo _blo += blo _bhi += blo if tag == "replace": self.replace_dissimilar(_alo, _ahi, _blo, _bhi) elif tag == "delete": self.delete(_alo, _ahi, _blo, _bhi) elif tag == "insert": self.insert(_alo, _ahi, _blo, _bhi) elif tag == "equal": self.replace_similar(_alo, _ahi, _blo, _bhi) else: raise ValueError, "unknown tag %s" % (tag,) def replace_similar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write("| ") a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName self.dumpCallNos(a_call.no, b_call.no) self.highlighter.bold(True) self.highlighter.write(b_call.functionName) self.highlighter.bold(False) self.highlighter.write("(") sep = "" numArgs = max(len(a_call.args), len(b_call.args)) for j in xrange(numArgs): self.highlighter.write(sep) try: a_argName, a_argVal = a_call.args[j] except IndexError: pass try: b_argName, b_argVal = b_call.args[j] except IndexError: pass self.replace_value(a_argName, b_argName) self.highlighter.write(" = ") self.replace_value(a_argVal, b_argVal) sep = ", " self.highlighter.write(")") if a_call.ret is not None or b_call.ret is not None: self.highlighter.write(" = ") self.replace_value(a_call.ret, b_call.ret) self.highlighter.write("\n") def replace_dissimilar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi if bhi - blo < ahi - alo: self.insert(alo, alo, blo, bhi) self.delete(alo, ahi, bhi, bhi) else: self.delete(alo, ahi, blo, blo) self.insert(ahi, ahi, blo, bhi) def replace_value(self, a, b): if b == a: self.highlighter.write(self.dumper.visit(b)) else: self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(self.dumper.visit(a)) self.highlighter.normal() self.highlighter.write(" -> ") self.highlighter.color(self.insert_color) self.highlighter.write(self.dumper.visit(b)) self.highlighter.normal() escape = "\33[" def delete(self, alo, ahi, blo, bhi): assert alo < ahi assert blo == bhi for i in xrange(alo, ahi): call = self.a[i] self.highlighter.write("- ") self.dumpCallNos(call.no, None) self.highlighter.strike() self.highlighter.color(self.delete_color) self.dumpCall(call) def insert(self, alo, ahi, blo, bhi): assert alo == ahi assert blo < bhi for i in xrange(blo, bhi): call = self.b[i] self.highlighter.write("+ ") self.dumpCallNos(None, call.no) self.highlighter.color(self.insert_color) self.dumpCall(call) def equal(self, alo, ahi, blo, bhi): if self.suppressCommonLines: return assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write(" ") a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.dumpCall(b_call) def dumpCallNos(self, aNo, bNo): if not self.callNos: return if aNo is not None and bNo is not None and aNo == bNo: aNoStr = str(aNo) self.highlighter.write(aNoStr) self.aSpace = len(aNoStr) self.bSpace = self.aSpace self.highlighter.write(" ") return if aNo is None: self.highlighter.write(" " * self.aSpace) else: aNoStr = str(aNo) self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(aNoStr) self.highlighter.normal() self.aSpace = len(aNoStr) self.highlighter.write(" ") if bNo is None: self.highlighter.write(" " * self.bSpace) else: bNoStr = str(bNo) self.highlighter.color(self.insert_color) self.highlighter.write(bNoStr) self.highlighter.normal() self.bSpace = len(bNoStr) self.highlighter.write(" ") def dumpCall(self, call): self.highlighter.bold(True) self.highlighter.write(call.functionName) self.highlighter.bold(False) self.highlighter.write("(" + self.dumper.visitItems(call.args) + ")") if call.ret is not None: self.highlighter.write(" = " + self.dumper.visit(call.ret)) self.highlighter.normal() self.highlighter.write("\n")
class PythonDiffer(Differ): def __init__(self, apitrace, callNos = False): Differ.__init__(self, apitrace) self.a = None self.b = None if self.isatty: self.highlighter = LessHighlighter() else: self.highlighter = PlainHighlighter() self.delete_color = self.highlighter.red self.insert_color = self.highlighter.green self.callNos = callNos self.aSpace = 0 self.bSpace = 0 self.dumper = Dumper() def setRefTrace(self, ref_trace, ref_calls): self.a = self.readTrace(ref_trace, ref_calls) def setSrcTrace(self, src_trace, src_calls): self.b = self.readTrace(src_trace, src_calls) def readTrace(self, trace, calls): p = subprocess.Popen( args = [ self.apitrace, 'pickle', '--symbolic', '--calls=' + calls, trace ], stdout = subprocess.PIPE, ) parser = Loader(p.stdout) parser.parse() return parser.calls def diff(self): try: self._diff() except IOError: pass def _diff(self): matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b) for tag, alo, ahi, blo, bhi in matcher.get_opcodes(): if tag == 'replace': self.replace(alo, ahi, blo, bhi) elif tag == 'delete': self.delete(alo, ahi, blo, bhi) elif tag == 'insert': self.insert(alo, ahi, blo, bhi) elif tag == 'equal': self.equal(alo, ahi, blo, bhi) else: raise ValueError, 'unknown tag %s' % (tag,) def isjunk(self, call): return call.functionName == 'glGetError' and call.ret in ('GL_NO_ERROR', 0) def replace(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi a_names = [call.functionName for call in self.a[alo:ahi]] b_names = [call.functionName for call in self.b[blo:bhi]] matcher = difflib.SequenceMatcher(None, a_names, b_names) for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes(): _alo += alo _ahi += alo _blo += blo _bhi += blo if tag == 'replace': self.replace_dissimilar(_alo, _ahi, _blo, _bhi) elif tag == 'delete': self.delete(_alo, _ahi, _blo, _bhi) elif tag == 'insert': self.insert(_alo, _ahi, _blo, _bhi) elif tag == 'equal': self.replace_similar(_alo, _ahi, _blo, _bhi) else: raise ValueError, 'unknown tag %s' % (tag,) def replace_similar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write('| ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName self.dumpCallNos(a_call.no, b_call.no) self.highlighter.bold(True) self.highlighter.write(b_call.functionName) self.highlighter.bold(False) self.highlighter.write('(') sep = '' numArgs = max(len(a_call.args), len(b_call.args)) for j in xrange(numArgs): self.highlighter.write(sep) try: a_arg = a_call.args[j] except IndexError: pass try: b_arg = b_call.args[j] except IndexError: pass self.replace_value(a_arg, b_arg) sep = ', ' self.highlighter.write(')') if a_call.ret is not None or b_call.ret is not None: self.highlighter.write(' = ') self.replace_value(a_call.ret, b_call.ret) self.highlighter.write('\n') def replace_dissimilar(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi if bhi - blo < ahi - alo: self.insert(alo, alo, blo, bhi) self.delete(alo, ahi, bhi, bhi) else: self.delete(alo, ahi, blo, blo) self.insert(ahi, ahi, blo, bhi) def replace_value(self, a, b): if b == a: self.highlighter.write(self.dumper.visit(b)) else: self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(self.dumper.visit(a)) self.highlighter.normal() self.highlighter.write(" ") self.highlighter.color(self.insert_color) self.highlighter.write(self.dumper.visit(b)) self.highlighter.normal() escape = "\33[" def delete(self, alo, ahi, blo, bhi): assert alo < ahi assert blo == bhi for i in xrange(alo, ahi): call = self.a[i] self.highlighter.write('- ') self.dumpCallNos(call.no, None) self.highlighter.strike() self.highlighter.color(self.delete_color) self.dumpCall(call) def insert(self, alo, ahi, blo, bhi): assert alo == ahi assert blo < bhi for i in xrange(blo, bhi): call = self.b[i] self.highlighter.write('+ ') self.dumpCallNos(None, call.no) self.highlighter.color(self.insert_color) self.dumpCall(call) def equal(self, alo, ahi, blo, bhi): assert alo < ahi and blo < bhi assert ahi - alo == bhi - blo for i in xrange(0, bhi - blo): self.highlighter.write(' ') a_call = self.a[alo + i] b_call = self.b[blo + i] assert a_call.functionName == b_call.functionName assert len(a_call.args) == len(b_call.args) self.dumpCallNos(a_call.no, b_call.no) self.dumpCall(b_call) def dumpCallNos(self, aNo, bNo): if not self.callNos: return if aNo is not None and bNo is not None and aNo == bNo: aNoStr = str(aNo) self.highlighter.write(aNoStr) self.aSpace = len(aNoStr) self.bSpace = self.aSpace self.highlighter.write(' ') return if aNo is None: self.highlighter.write(' '*self.aSpace) else: aNoStr = str(aNo) self.highlighter.strike() self.highlighter.color(self.delete_color) self.highlighter.write(aNoStr) self.highlighter.normal() self.aSpace = len(aNoStr) self.highlighter.write(' ') if bNo is None: self.highlighter.write(' '*self.bSpace) else: bNoStr = str(bNo) self.highlighter.color(self.insert_color) self.highlighter.write(bNoStr) self.highlighter.normal() self.bSpace = len(bNoStr) self.highlighter.write(' ') def dumpCall(self, call): self.highlighter.bold(True) self.highlighter.write(call.functionName) self.highlighter.bold(False) self.highlighter.write('(' + ', '.join(itertools.imap(self.dumper.visit, call.args)) + ')') if call.ret is not None: self.highlighter.write(' = ' + self.dumper.visit(call.ret)) self.highlighter.normal() self.highlighter.write('\n')