diff --git a/sandbox/Debug.py b/sandbox/Debug.py index 2d75fe9ff..c560b6f21 100644 --- a/sandbox/Debug.py +++ b/sandbox/Debug.py @@ -55,13 +55,6 @@ def configure(advanced): from questions import expect, anything, something, yn conf.registerPlugin('Debug', True) -def getTracer(fd): - def tracer(frame, event, _): - if event == 'call': - code = frame.f_code - print >>fd, '%s: %s' % (code.co_filename, code.co_name) - return tracer - class Debug(privmsgs.CapabilityCheckingPrivmsg): capability = 'owner' @@ -104,7 +97,7 @@ class Debug(privmsgs.CapabilityCheckingPrivmsg): fd = file(filename, 'a') else: fd = sys.stdout - sys.settrace(getTracer(fd)) + sys.settrace(utils.callTracer(fd)) irc.replySuccess() def unsettrace(self, irc, msg, args): diff --git a/src/utils.py b/src/utils.py index ebc52eb55..17d672f52 100755 --- a/src/utils.py +++ b/src/utils.py @@ -490,7 +490,6 @@ def saltHash(password, salt=None, hash='sha'): def safeEval(s, namespace={'True': True, 'False': False, 'None': None}): """Evaluates s, safely. Useful for turning strings into tuples/lists/etc. without unsafely using eval().""" - #print s, '::', stackTrace() try: node = compiler.parse(s) except SyntaxError, e: @@ -704,21 +703,6 @@ def mungeEmailForWeb(s): s = s.replace('.', ' DOT ') return s -def stackTrace(frame=None, compact=True): - if frame is None: - frame = sys._getframe() - if compact: - L = [] - while frame: - lineno = frame.f_lineno - funcname = frame.f_code.co_name - filename = os.path.basename(frame.f_code.co_filename) - L.append('[%s|%s|%s]' % (filename, funcname, lineno)) - frame = frame.f_back - return textwrap.fill(' '.join(L)) - else: - return traceback.format_stack(frame) - class AtomicFile(file): """Used for files that need to be atomically written -- i.e., if there's a failure, the original file remains, unmodified. mode must be 'w' or 'wb'""" @@ -773,6 +757,35 @@ def transactionalFile(*args, **kwargs): # We do that replacement in conf.py. return AtomicFile(*args, **kwargs) +def stackTrace(frame=None, compact=True): + if frame is None: + frame = sys._getframe() + if compact: + L = [] + while frame: + lineno = frame.f_lineno + funcname = frame.f_code.co_name + filename = os.path.basename(frame.f_code.co_filename) + L.append('[%s|%s|%s]' % (filename, funcname, lineno)) + frame = frame.f_back + return textwrap.fill(' '.join(L)) + else: + return traceback.format_stack(frame) + +def callTracer(fd=None, basename=True): + if fd is None: + fd = sys.stdout + def tracer(frame, event, _): + if event == 'call': + code = frame.f_code + lineno = frame.f_lineno + funcname = code.co_name + filename = code.co_filename + if basename: + filename = os.path.basename(filename) + print >>fd, '%s: %s(%s)' % (filename, funcname, lineno) + return tracer + if __name__ == '__main__': import doctest doctest.testmod(sys.modules['__main__']) diff --git a/test/test.py b/test/test.py index f24621319..cf6ae7c02 100755 --- a/test/test.py +++ b/test/test.py @@ -70,10 +70,13 @@ conf.supybot.flush.setValue(False) import supybot.fix as fix import re +import sys import glob +import atexit import os.path import unittest +import supybot.utils as utils import supybot.world as world class path(str): @@ -123,6 +126,8 @@ if __name__ == '__main__': help='Causes the network-based tests not to run.') parser.add_option('', '--noplugins', action='store_true', default=False, help='Causes the plugin tests not to run.') + parser.add_option('', '--trace', action='store_true', default=False, + help='Traces all calls made.') (options, args) = parser.parse_args() if not args: if options.noplugins: @@ -143,6 +148,13 @@ if __name__ == '__main__': if options.timeout: PluginTestCase.timeout = options.timeout + if options.trace: + traceFilename = conf.supybot.directories.log.dirize('trace.log') + fd = file(traceFilename, 'w') + sys.settrace(utils.callTracer(fd)) + atexit.register(fd.close) + atexit.register(lambda : sys.settrace(None)) + if options.plugindirs: options.plugindirs.reverse() conf.pluginDirs.extend(options.plugindirs)