#!/usr/bin/env python3 # # See the accompanying LICENSE file. # # This module lets you automatically trace SQL operations in a program # using APSW without having to modify the program in any way. import time import sys import weakref class APSWTracer(object): def __init__(self, options): self.u="" import _thread self.threadid=_thread.get_ident self.stringtypes=(str,) self.numtypes=(int, float) self.binarytypes=(bytes,) self.options=options if options.output in ("-", "stdout"): self._writer=sys.stdout.write elif options.output=="stderr": self._writer=sys.stderr.write else: self._writer=open(options.output, "wt").write try: import apsw apsw.connection_hooks.append(self.connection_hook) except: sys.stderr.write(self.u+"Unable to import apsw\n") raise self.mapping_open_flags=apsw.mapping_open_flags self.zeroblob=apsw.zeroblob self.apswConnection=apsw.Connection self.newcursor={} self.threadsused={} # really want a set self.queries={} self.timings={} self.rowsreturned=0 self.numcursors=0 self.numconnections=0 self.timestart=time.time() def writerpy3(self, s): self._writer(s+"\n") writer=writerpy3 def format(self, obj): if isinstance(obj, dict): return self.formatdict(obj) if isinstance(obj, tuple): return self.formatseq(obj, '()') if isinstance(obj, list): return self.formatseq(obj, '[]') if isinstance(obj, self.stringtypes): return self.formatstring(obj) if obj is True: return "True" if obj is False: return "False" if obj is None: return "None" if isinstance(obj, self.numtypes): return repr(obj) if isinstance(obj, self.binarytypes): return self.formatbinary(obj) if isinstance(obj, self.zeroblob): return "zeroblob(%d)" % (obj.length(),) return repr(obj) def formatstring(self, obj, quote='"', checkmaxlen=True): obj=obj.replace("\n", "\\n").replace("\r", "\\r") if checkmaxlen and len(obj)>self.options.length: obj=obj[:self.options.length]+'..' return self.u+quote+obj+quote def formatdict(self, obj): items=list(obj.items()) items.sort() op=[] for k,v in items: op.append(self.format(k)+": "+self.format(v)) return self.u+"{"+", ".join(op)+"}" def formatseq(self, obj, paren): return self.u+paren[0]+", ".join([self.format(v) for v in obj])+paren[1] def formatbinary(self, obj): if len(obj)