]> git.cworth.org Git - apitrace/commitdiff
Improve tracediff2's dumping.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sat, 17 Mar 2012 17:23:39 +0000 (17:23 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Sat, 17 Mar 2012 17:23:39 +0000 (17:23 +0000)
scripts/tracediff2.py
scripts/unpickle.py

index 13fcbd1ef991ffbd6e6c63e032b6f756eb09911c..3f14d36d2410f204594b922e2bb08d96b0ab749b 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 ##########################################################################
 #
-# Copyright 2011 Jose Fonseca
+# Copyright 2011-2012 Jose Fonseca
 # All Rights Reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 
 
 import difflib
+import itertools
 import optparse
 import os.path
 import subprocess
 import sys
 
-from unpickle import Unpickler
+from unpickle import Unpickler, Dumper
 from highlight import ColorHighlighter, LessHighlighter
 
 
@@ -86,6 +87,7 @@ class SDiffer:
         self.callNos = callNos
         self.aSpace = 0
         self.bSpace = 0
+        self.dumper = Dumper()
 
     def diff(self):
         matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b)
@@ -167,15 +169,15 @@ class SDiffer:
 
     def replace_value(self, a, b):
         if b == a:
-            self.highlighter.write(str(b))
+            self.highlighter.write(self.dumper.visit(b))
         else:
             self.highlighter.strike()
             self.highlighter.color(self.delete_color)
-            self.highlighter.write(str(a))
+            self.highlighter.write(self.dumper.visit(a))
             self.highlighter.normal()
             self.highlighter.write(" ")
             self.highlighter.color(self.insert_color)
-            self.highlighter.write(str(b))
+            self.highlighter.write(self.dumper.visit(b))
             self.highlighter.normal()
 
     escape = "\33["
@@ -235,9 +237,9 @@ class SDiffer:
         self.highlighter.bold(True)
         self.highlighter.write(call.functionName)
         self.highlighter.bold(False)
-        self.highlighter.write('(' + ', '.join(map(repr, call.args)) + ')')
+        self.highlighter.write('(' + ', '.join(itertools.imap(self.dumper.visit, call.args)) + ')')
         if call.ret is not None:
-            self.highlighter.write(' = ' + repr(call.ret))
+            self.highlighter.write(' = ' + self.dumper.visit(call.ret))
         self.highlighter.normal()
         self.highlighter.write('\n')
 
index 98e2c30b4505d27d6b779200d38382a74004addf..3f0bc42fc34ce6c1b01a9128ddaddeda754d9ab1 100755 (executable)
@@ -33,10 +33,100 @@ Run as:
 '''
 
 
+import itertools
 import optparse
-import cPickle as pickle
 import sys
 import time
+import re
+import cPickle as pickle
+
+
+class Visitor:
+
+    def __init__(self):
+        self.dispatch = {}
+        self.dispatch[type(None)] = self.visitNone
+        self.dispatch[bool] = self.visitBool
+        self.dispatch[int] = self.visitInt
+        self.dispatch[long] = self.visitInt
+        self.dispatch[float] = self.visitFloat
+        self.dispatch[str] = self.visitStr
+        self.dispatch[tuple] = self.visitTuple
+        self.dispatch[list] = self.visitList
+        self.dispatch[dict] = self.visitDict
+        self.dispatch[bytearray] = self.visitByteArray
+
+    def visit(self, obj, *args, **kwargs):
+        return self.dispatch[type(obj)](obj, *args, **kwargs)
+
+    def visitAtom(self, obj, *args, **kwargs):
+        raise NotImplementedError
+
+    def visitNone(self, obj, *args, **kwargs):
+        return self.visitAtom(obj, *args, **kwargs)
+
+    def visitBool(self, obj, *args, **kwargs):
+        return self.visitAtom(obj, *args, **kwargs)
+
+    def visitInt(self, obj, *args, **kwargs):
+        return self.visitAtom(obj, *args, **kwargs)
+
+    def visitFloat(self, obj, *args, **kwargs):
+        return self.visitAtom(obj, *args, **kwargs)
+
+    def visitStr(self, obj, *args, **kwargs):
+        return self.visitAtom(obj, *args, **kwargs)
+
+    def visitIterable(self, obj, *args, **kwargs):
+        raise NotImplementedError
+
+    def visitTuple(self, obj, *args, **kwargs):
+        return self.visitIterable(obj, *args, **kwargs)
+
+    def visitList(self, obj, *args, **kwargs):
+        return self.visitIterable(obj, *args, **kwargs)
+
+    def visitDict(self, obj, *args, **kwargs):
+        raise NotImplementedError
+
+    def visitByteArray(self, obj, *args, **kwargs):
+        raise NotImplementedError
+
+
+class Dumper(Visitor):
+
+    id_re = re.compile('^[_A-Za-z][_A-Za-z0-9]*$')
+
+    def visitAtom(self, obj, *args, **kwargs):
+        return repr(obj)
+
+    def visitStr(self, obj, *args, **kwargs):
+        if self.id_re.match(obj):
+            return obj
+        else:
+            return repr(obj)
+
+    def visitTuple(self, obj, *args, **kwargs):
+        return '[' + ', '.join(itertools.imap(self.visit, obj)) + ']'
+
+    def visitList(self, obj, *args, **kwargs):
+        return '(' + ', '.join(itertools.imap(self.visit, obj)) + ')'
+
+    def visitByteArray(self, obj, *args, **kwargs):
+        return 'blob(%u)' % len(obj)
+
+
+class Hasher(Visitor):
+    '''Returns a hashable version of the objtree.'''
+
+    def visitAtom(self, obj, *args, **kwargs):
+        return obj
+
+    def visitIterable(self, obj, *args, **kwargs):
+        return tuple(itertools.imap(self.visit, obj))
+
+    def visitByteArray(self, obj, *args, **kwargs):
+        return str(obj)
 
 
 class Call:
@@ -49,10 +139,11 @@ class Call:
         s = self.functionName
         if self.no is not None:
             s = str(self.no) + ' ' + s
-        s += '(' + ', '.join(map(repr, self.args)) + ')'
+        dumper = Dumper()
+        s += '(' + ', '.join(itertools.imap(dumper.visit, self.args)) + ')'
         if self.ret is not None:
             s += ' = '
-            s += repr(self.ret)
+            s += dumper.visit(self.ret)
         return s
 
     def __eq__(self, other):
@@ -63,9 +154,9 @@ class Call:
 
     def __hash__(self):
         if self._hash is None:
-            # XXX: hack due to unhashable types
-            #self._hash = hash(self.functionName) ^ hash(tuple(self.args)) ^ hash(self.ret)
-            self._hash = hash(self.functionName) ^ hash(repr(self.args)) ^ hash(repr(self.ret))
+            hasher = Hasher()
+            hashable = hasher.visit(self.functionName), hasher.visit(self.args), hasher.visit(self.ret)
+            self._hash = hash(hashable)
         return self._hash