Fix rpdb not working on py3

This commit is contained in:
Kovid Goyal 2021-02-09 23:44:53 +05:30
parent a4cd28d746
commit 2880e83d1a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -6,10 +6,9 @@ __license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import pdb, socket, inspect, sys, select, os, atexit, time import pdb, socket, inspect, sys, select, os, atexit, time
from contextlib import suppress
from calibre import prints
from calibre.constants import cache_dir from calibre.constants import cache_dir
from polyglot.builtins import range, raw_input as rinput
PROMPT = '(debug) ' PROMPT = '(debug) '
QUESTION = '\x00\x01\x02' QUESTION = '\x00\x01\x02'
@ -18,24 +17,24 @@ QUESTION = '\x00\x01\x02'
class RemotePdb(pdb.Pdb): class RemotePdb(pdb.Pdb):
def __init__(self, addr="127.0.0.1", port=4444, skip=None): def __init__(self, addr="127.0.0.1", port=4444, skip=None):
try:
prints("pdb is running on %s:%d" % (addr, port), file=sys.stderr)
except IOError:
pass
# Open a reusable socket to allow for reloads # Open a reusable socket to allow for reloads
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.sock.bind((addr, port)) self.sock.bind((addr, port))
self.sock.listen(1) self.sock.listen(1)
with suppress(OSError):
print("pdb is running on %s:%d" % (addr, port), file=sys.stderr)
clientsocket, address = self.sock.accept() clientsocket, address = self.sock.accept()
clientsocket.setblocking(True)
self.clientsocket = clientsocket
self.handle = clientsocket.makefile('rw') self.handle = clientsocket.makefile('rw')
pdb.Pdb.__init__(self, completekey='tab', stdin=self.handle, stdout=self.handle, skip=skip) pdb.Pdb.__init__(self, completekey='tab', stdin=self.handle, stdout=self.handle, skip=skip)
self.prompt = PROMPT self.prompt = PROMPT
def prints(self, *args, **kwargs): def prints(self, *args, **kwargs):
kwargs['file'] = self.handle kwargs['file'] = self.handle
prints(*args, **kwargs) kwargs['flush'] = True
print(*args, **kwargs)
def ask_question(self, query): def ask_question(self, query):
self.handle.write(QUESTION) self.handle.write(QUESTION)
@ -47,7 +46,9 @@ class RemotePdb(pdb.Pdb):
def end_session(self, *args): def end_session(self, *args):
self.clear_all_breaks() self.clear_all_breaks()
self.reset() self.reset()
del self.handle self.handle.close()
self.clientsocket.shutdown(socket.SHUT_RDWR)
self.clientsocket.close()
try: try:
self.sock.shutdown(socket.SHUT_RDWR) self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close() self.sock.close()
@ -85,15 +86,15 @@ def set_trace(port=4444, skip=None):
debugger = RemotePdb(port=port, skip=skip) debugger = RemotePdb(port=port, skip=skip)
debugger.set_trace(frame) debugger.set_trace(frame)
except KeyboardInterrupt: except KeyboardInterrupt:
prints('Debugging aborted by keyboard interrupt') print('Debugging aborted by keyboard interrupt')
except Exception: except Exception:
prints('Failed to run debugger') print('Failed to run debugger')
import traceback import traceback
traceback.print_exc() traceback.print_exc()
def cli(port=4444): def cli(port=4444):
prints('Connecting to remote debugger on port %d...' % port) print('Connecting to remote debugger on port %d...' % port)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for i in range(20): for i in range(20):
try: try:
@ -106,48 +107,51 @@ def cli(port=4444):
try: try:
sock.connect(('127.0.0.1', port)) sock.connect(('127.0.0.1', port))
except socket.error as err: except socket.error as err:
prints('Failed to connect to remote debugger:', err, file=sys.stderr) print('Failed to connect to remote debugger:', err, file=sys.stderr)
raise SystemExit(1) raise SystemExit(1)
prints('Connected to remote process') print('Connected to remote process', flush=True)
import readline
histfile = os.path.join(cache_dir(), 'rpdb.history')
try: try:
readline.read_history_file(histfile) import readline
except IOError: histfile = os.path.join(cache_dir(), 'rpdb.history')
try:
readline.read_history_file(histfile)
except IOError:
pass
atexit.register(readline.write_history_file, histfile)
p = pdb.Pdb()
readline.set_completer(p.complete)
readline.parse_and_bind("tab: complete")
except ImportError:
pass pass
atexit.register(readline.write_history_file, histfile) sock.setblocking(True)
p = pdb.Pdb() with suppress(KeyboardInterrupt):
readline.set_completer(p.complete) end_of_input = PROMPT.encode('utf-8')
readline.parse_and_bind("tab: complete")
sockf = sock.makefile('rw')
try:
while True: while True:
recvd = '' recvd = b''
while not recvd.endswith(PROMPT) or select.select([sock], [], [], 0) == ([sock], [], []): while select.select([sock], [], [], 0)[0] or not recvd.endswith(end_of_input):
buf = sockf.read() buf = sock.recv(4096)
if not buf: if not buf:
return return
recvd += buf recvd += buf
recvd = recvd.decode('utf-8', 'replace')
recvd = recvd[:-len(PROMPT)] recvd = recvd[:-len(PROMPT)]
raw = ''
if recvd.startswith(QUESTION): if recvd.startswith(QUESTION):
recvd = recvd[len(QUESTION):] recvd = recvd[len(QUESTION):]
sys.stdout.write(recvd) print(recvd, end='', flush=True)
raw = sys.stdin.readline() or 'n' raw = sys.stdin.readline() or 'n'
else: else:
sys.stdout.write(recvd) print(recvd, end='', flush=True)
raw = ''
try: try:
raw = rinput(PROMPT.decode('utf-8')) raw = input(PROMPT)
except (EOFError, KeyboardInterrupt): except (EOFError, KeyboardInterrupt):
pass pass
else: else:
raw += '\n' raw += '\n'
if not raw: if not raw:
raw = 'quit\n' raw = 'quit\n'
sockf.write(raw) if raw:
except KeyboardInterrupt: sock.sendall(raw.encode('utf-8'))
pass
if __name__ == '__main__': if __name__ == '__main__':