This commit is contained in:
Massimo Di Pierro
2012-02-19 22:30:59 -06:00
parent cf9c827661
commit 4f1d3e79b4
12 changed files with 353 additions and 7 deletions
+100
View File
@@ -10,6 +10,7 @@ License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
"""
import logging
import os
import pdb
import Queue
import sys
@@ -82,7 +83,106 @@ def communicate(command=None):
return ''.join(result)
# New debugger implementation using qdb and a web UI
import gluon.contrib.qdb as qdb
from gluon import portalocker
def lock(name=''):
from gluon.globals import current
locker = open(os.path.join(current.request.folder, 'debug_%s.lock' % name),
'a')
portalocker.lock(locker, portalocker.LOCK_EX)
return locker
def unlock(locker):
portalocker.unlock(locker)
locker.close()
def check_interaction(fn):
"Decorator to clean and prevent interaction when not available"
def check_fn(self, *args, **kwargs):
locker = lock('interact')
try:
if self.filename:
self.clear_interaction()
fn(self, *args, **kwargs)
finally:
unlock(locker)
return check_fn
class WebDebugger(qdb.Frontend):
"Qdb web2py interface"
def __init__(self, pipe, completekey='tab', stdin=None, stdout=None, skip=None):
qdb.Frontend.__init__(self, pipe)
self.clear_interaction()
def clear_interaction(self):
self.filename = None
self.lineno = None
self.exception_info = None
# redefine Frontend methods:
def run(self):
locker = lock('run')
try:
while self.pipe.poll():
qdb.Frontend.run(self)
finally:
unlock(locker)
def interaction(self, filename, lineno, line):
# store current status
locker = lock('interact')
try:
self.filename = filename
self.lineno = lineno
finally:
unlock(locker)
def exception(self, title, extype, exvalue, trace, request):
self.exception_info = {'title': title,
'extype': extype, 'exvalue': exvalue,
'trace': trace, 'request': request}
@check_interaction
def do_continue(self):
qdb.Frontend.do_continue(self)
@check_interaction
def do_step(self):
qdb.Frontend.do_step(self)
@check_interaction
def do_return(self):
qdb.Frontend.do_return(self)
@check_interaction
def do_next(self):
qdb.Frontend.do_next(self)
@check_interaction
def do_quit(self):
qdb.Frontend.do_quit(self)
# create the connection between threads:
parent_queue, child_queue = Queue.Queue(), Queue.Queue()
front_conn = qdb.QueuePipe("parent", parent_queue, child_queue)
child_conn = qdb.QueuePipe("child", child_queue, parent_queue)
web_debugger = WebDebugger(front_conn) # frontend
qdb_debugger = qdb.Qdb(pipe=child_conn, redirect_stdio=False) # backend
dbg = qdb_debugger
import gluon.main
gluon.main.global_settings.debugging = True