#!/usr/bin/python

import sys
from twisted.internet import threads, reactor, defer

class ThreadedDebugger(object):
    def __init__(self, runme):
        self._runme = runme

    def _runInThread(self):
        try:
            sys.settrace(self._tracefunc)
            exec self._runme
        finally:
            sys.settrace(None)

    def go(self):
        reactor.callInThread(self._runInThread)

    def _tracefunc(self, frame, event, arg):
        if "<string>" in frame.f_code.co_filename:
            threads.blockingCallFromThread(reactor, self._traceLine, frame.f_lineno)
        return self._tracefunc
        
    def _traceLine(self, lineno):
        print "On line %d: %s" %(lineno, self._runme.split("\n")[lineno-1])
        d = defer.Deferred()
        reactor.callLater(0.5, d.callback, None)
        return d

db = ThreadedDebugger("""print 5
print 3
for i in range(4):
    print i
print 8""")

reactor.callWhenRunning(db.go)

def loopForever():
    print "looping..."
    reactor.callLater(0.7, loopForever)
#reactor.callWhenRunning(loopForever)

reactor.run()

