PythonOnlineDebugger/console.py

116 lines
2.8 KiB
Python

# Forked from https://raw.githubusercontent.com/romanvm/python-web-pdb
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
import weakref
from threading import Event
from threading import RLock
try:
import queue
except ImportError:
import Queue as queue
class ThreadSafeObject(object):
"""
An object for data exchange between threads
"""
def __init__(self, contents=None):
self._lock = RLock()
self._contents = contents
@property
def contents(self):
with self._lock:
return self._contents
@contents.setter
def contents(self, value):
with self._lock:
self._contents = value
class Console(object):
input_queue = queue.Queue()
def __init__(self, debugger):
self.pdb_not_busy = Event()
self.closed = False
self._debugger = weakref.proxy(debugger)
self._console_history = ThreadSafeObject("")
self._frame_data = ThreadSafeObject({})
self._output_lock = RLock()
self.exception = None
@property
def seekable(self):
return False
@property
def writable(self):
return True
@property
def encoding(self):
return "utf-8"
def close(self):
self.closed = True
self.pdb_not_busy.set()
def readline(self):
self.pdb_not_busy.set()
command = self.input_queue.get()
self.pdb_not_busy.clear()
if not command:
command = "\n"
with open("commands.txt", "a+") as file:
file.write(command)
self.writeline(command)
return command
read = readline
def writeline(self, data):
with self._output_lock:
if isinstance(data, bytes):
data = data.decode("utf-8")
self._console_history.contents += data
try:
frame_data = self._debugger.get_current_frame_data()
except (IOError, AttributeError):
frame_data = {
"dirname": "",
"filename": "",
"file_listing": "No data available",
"current_line": -1,
"breakpoints": [],
"globals": {},
"locals": {},
"expressions": {},
"exception": sys.exc_info(),
}
frame_data["console_history"] = self._console_history.contents
self._frame_data.contents = frame_data
write = writeline
def flush(self):
pass
def send_pdb_command(self, command):
self.pdb_not_busy.wait()
self.input_queue.put(command)
def get_frame_data(self):
with self._output_lock:
return self._frame_data.contents