Example #1
0
 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()
Example #2
0
 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()
Example #3
0
 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()
Example #4
0
 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()
Example #5
0
 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()
Example #6
0
 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()
Example #7
0
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')
Example #8
0
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')
Example #9
0
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')
Example #10
0
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")
Example #11
0
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')