source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/debug.py @ 42095c5

mainqndtest v1.1.1
Last change on this file since 42095c5 was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 5.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4"""
5| This file is part of the web2py Web Framework
6| Developed by Massimo Di Pierro <mdipierro@cs.depaul.edu>,
7| limodou <limodou@gmail.com> and srackham <srackham@gmail.com>.
8| License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
9
10Debugger support classes
11------------------------
12"""
13
14import logging
15import pdb
16import sys
17from gluon._compat import Queue
18
19logger = logging.getLogger("web2py")
20
21
22class Pipe(Queue.Queue):
23    def __init__(self, name, mode='r', *args, **kwargs):
24        self.__name = name
25        Queue.Queue.__init__(self, *args, **kwargs)
26
27    def write(self, data):
28        logger.debug("debug %s writing %s" % (self.__name, data))
29        self.put(data)
30
31    def flush(self):
32        # mark checkpoint (complete message)
33        logger.debug("debug %s flushing..." % self.__name)
34        self.put(None)
35        # wait until it is processed
36        self.join()
37        logger.debug("debug %s flush done" % self.__name)
38
39    def read(self, count=None, timeout=None):
40        logger.debug("debug %s reading..." % (self.__name, ))
41        data = self.get(block=True, timeout=timeout)
42        # signal that we are ready
43        self.task_done()
44        logger.debug("debug %s read %s" % (self.__name, data))
45        return data
46
47    def readline(self):
48        logger.debug("debug %s readline..." % (self.__name, ))
49        return self.read()
50
51
52pipe_in = Pipe('in')
53pipe_out = Pipe('out')
54
55debugger = pdb.Pdb(completekey=None, stdin=pipe_in, stdout=pipe_out,)
56
57
58def set_trace():
59    """breakpoint shortcut (like pdb)"""
60    logger.info("DEBUG: set_trace!")
61    debugger.set_trace(sys._getframe().f_back)
62
63
64def stop_trace():
65    """stop waiting for the debugger (called atexit)"""
66    # this should prevent communicate is wait forever a command result
67    # and the main thread has finished
68    logger.info("DEBUG: stop_trace!")
69    pipe_out.write("debug finished!")
70    pipe_out.write(None)
71    #pipe_out.flush()
72
73
74def communicate(command=None):
75    """send command to debbuger, wait result"""
76    if command is not None:
77        logger.info("DEBUG: sending command %s" % command)
78        pipe_in.write(command)
79        #pipe_in.flush()
80    result = []
81    while True:
82        data = pipe_out.read()
83        if data is None:
84            break
85        result.append(data)
86    logger.info("DEBUG: result %s" % repr(result))
87    return ''.join(result)
88
89
90# New debugger implementation using dbg and a web UI
91
92import gluon.contrib.dbg as c_dbg
93from threading import RLock
94
95interact_lock = RLock()
96run_lock = RLock()
97
98
99def check_interaction(fn):
100    """Decorator to clean and prevent interaction when not available"""
101    def check_fn(self, *args, **kwargs):
102        interact_lock.acquire()
103        try:
104            if self.filename:
105                self.clear_interaction()
106                return fn(self, *args, **kwargs)
107        finally:
108            interact_lock.release()
109    return check_fn
110
111
112class WebDebugger(c_dbg.Frontend):
113    """Qdb web2py interface"""
114
115    def __init__(self, pipe, completekey='tab', stdin=None, stdout=None):
116        c_dbg.Frontend.__init__(self, pipe)
117        self.clear_interaction()
118
119    def clear_interaction(self):
120        self.filename = None
121        self.lineno = None
122        self.exception_info = None
123        self.context = None
124
125    # redefine Frontend methods:
126
127    def run(self):
128        run_lock.acquire()
129        try:
130            while self.pipe.poll():
131                c_dbg.Frontend.run(self)
132        finally:
133            run_lock.release()
134
135    def interaction(self, filename, lineno, line, **context):
136        # store current status
137        interact_lock.acquire()
138        try:
139            self.filename = filename
140            self.lineno = lineno
141            self.context = context
142        finally:
143            interact_lock.release()
144
145    def exception(self, title, extype, exvalue, trace, request):
146        self.exception_info = {'title': title,
147                               'extype': extype, 'exvalue': exvalue,
148                               'trace': trace, 'request': request}
149
150    @check_interaction
151    def do_continue(self):
152        c_dbg.Frontend.do_continue(self)
153
154    @check_interaction
155    def do_step(self):
156        c_dbg.Frontend.do_step(self)
157
158    @check_interaction
159    def do_return(self):
160        c_dbg.Frontend.do_return(self)
161
162    @check_interaction
163    def do_next(self):
164        c_dbg.Frontend.do_next(self)
165
166    @check_interaction
167    def do_quit(self):
168        c_dbg.Frontend.do_quit(self)
169
170    def do_exec(self, statement):
171        interact_lock.acquire()
172        try:
173            # check to see if we're inside interaction
174            if self.filename:
175                # avoid spurious interaction notifications:
176                self.set_burst(2)
177                # execute the statement in the remote debugger:
178                return c_dbg.Frontend.do_exec(self, statement)
179        finally:
180            interact_lock.release()
181
182# create the connection between threads:
183
184parent_queue, child_queue = Queue.Queue(), Queue.Queue()
185front_conn = c_dbg.QueuePipe("parent", parent_queue, child_queue)
186child_conn = c_dbg.QueuePipe("child", child_queue, parent_queue)
187
188web_debugger = WebDebugger(front_conn)                                     # frontend
189dbg_debugger = c_dbg.Qdb(pipe=child_conn, redirect_stdio=False, skip=None)   # backend
190dbg = dbg_debugger
191
192# enable getting context (stack, globals/locals) at interaction
193dbg_debugger.set_params(dict(call_stack=True, environment=True))
194
195import gluon.main
196gluon.main.global_settings.debugging = True
Note: See TracBrowser for help on using the repository browser.