~ubuntu-branches/debian/sid/calibre/sid

« back to all changes in this revision

Viewing changes to src/calibre/rpdb.py

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2014-05-14 18:17:50 UTC
  • mto: This revision was merged to the branch mainline in revision 75.
  • Revision ID: package-import@ubuntu.com-20140514181750-efj1wymey2vb4cao
Tags: upstream-1.36.0+dfsg
ImportĀ upstreamĀ versionĀ 1.36.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# vim:fileencoding=utf-8
 
3
from __future__ import (unicode_literals, division, absolute_import,
 
4
                        print_function)
 
5
 
 
6
__license__ = 'GPL v3'
 
7
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
 
8
 
 
9
import pdb, socket, inspect, sys, select, os, atexit, time
 
10
 
 
11
from calibre import prints
 
12
from calibre.utils.ipc import eintr_retry_call
 
13
from calibre.constants import cache_dir
 
14
 
 
15
PROMPT = b'(debug) '
 
16
QUESTION = b'\x00\x01\x02'
 
17
 
 
18
class RemotePdb(pdb.Pdb):
 
19
 
 
20
    def __init__(self, addr="127.0.0.1", port=4444, skip=None):
 
21
        try:
 
22
            prints("pdb is running on %s:%d" % (addr, port), file=sys.stderr)
 
23
        except IOError:
 
24
            pass
 
25
 
 
26
        # Open a reusable socket to allow for reloads
 
27
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
28
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
 
29
        self.sock.bind((addr, port))
 
30
        self.sock.listen(1)
 
31
        clientsocket, address = self.sock.accept()
 
32
        self.handle = clientsocket.makefile('rw')
 
33
        pdb.Pdb.__init__(self, completekey='tab', stdin=self.handle, stdout=self.handle, skip=skip)
 
34
        self.prompt = PROMPT
 
35
 
 
36
    def prints(self, *args, **kwargs):
 
37
        kwargs['file'] = self.handle
 
38
        prints(*args, **kwargs)
 
39
 
 
40
    def ask_question(self, query):
 
41
        self.handle.write(QUESTION)
 
42
        self.prints(query, end='')
 
43
        self.handle.write(PROMPT)
 
44
        self.handle.flush()
 
45
        return self.handle.readline()
 
46
 
 
47
    def end_session(self, *args):
 
48
        self.clear_all_breaks()
 
49
        self.reset()
 
50
        del self.handle
 
51
        try:
 
52
            self.sock.shutdown(socket.SHUT_RDWR)
 
53
            self.sock.close()
 
54
        except socket.error:
 
55
            pass
 
56
        return pdb.Pdb.do_continue(self, None)
 
57
 
 
58
    def do_clear(self, arg):
 
59
        if not arg:
 
60
            ans = self.ask_question("Clear all breaks? [y/n]: ")
 
61
            if ans.strip().lower() in {b'y', b'yes'}:
 
62
                self.clear_all_breaks()
 
63
                self.prints('All breaks cleared')
 
64
            return
 
65
        return pdb.Pdb.do_clear(self, arg)
 
66
    do_cl = do_clear
 
67
 
 
68
    def do_continue(self, arg):
 
69
        if not self.breaks:
 
70
            ans = self.ask_question(
 
71
                'There are no breakpoints set. Continuing will terminate this debug session. Are you sure? [y/n]: ')
 
72
            if ans.strip().lower() in {b'y', b'yes'}:
 
73
                return self.end_session()
 
74
            return
 
75
        return pdb.Pdb.do_continue(self, arg)
 
76
    do_c = do_cont = do_continue
 
77
 
 
78
    do_EOF = do_quit = do_exit = do_q = end_session
 
79
 
 
80
def set_trace(port=4444, skip=None):
 
81
    frame = inspect.currentframe().f_back
 
82
 
 
83
    try:
 
84
        debugger = RemotePdb(port=port, skip=skip)
 
85
        debugger.set_trace(frame)
 
86
    except KeyboardInterrupt:
 
87
        prints('Debugging aborted by keyboard interrupt')
 
88
    except Exception:
 
89
        prints('Failed to run debugger')
 
90
        import traceback
 
91
        traceback.print_exc()
 
92
 
 
93
def cli(port=4444):
 
94
    prints('Connecting to remote debugger on port %d...' % port)
 
95
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
96
    for i in xrange(20):
 
97
        try:
 
98
            sock.connect(('127.0.0.1', port))
 
99
            break
 
100
        except socket.error:
 
101
            pass
 
102
        time.sleep(0.1)
 
103
    else:
 
104
        try:
 
105
            sock.connect(('127.0.0.1', port))
 
106
        except socket.error as err:
 
107
            prints('Failed to connect to remote debugger:', err, file=sys.stderr)
 
108
            raise SystemExit(1)
 
109
    prints('Connected to remote process')
 
110
    import readline
 
111
    histfile = os.path.join(cache_dir(), 'rpdb.history')
 
112
    try:
 
113
        readline.read_history_file(histfile)
 
114
    except IOError:
 
115
        pass
 
116
    atexit.register(readline.write_history_file, histfile)
 
117
    p = pdb.Pdb()
 
118
    readline.set_completer(p.complete)
 
119
    readline.parse_and_bind("tab: complete")
 
120
 
 
121
    try:
 
122
        while True:
 
123
            recvd = b''
 
124
            while not recvd.endswith(PROMPT) or select.select([sock], [], [], 0) == ([sock], [], []):
 
125
                buf = eintr_retry_call(sock.recv, 16 * 1024)
 
126
                if not buf:
 
127
                    return
 
128
                recvd += buf
 
129
            recvd = recvd[:-len(PROMPT)]
 
130
            if recvd.startswith(QUESTION):
 
131
                recvd = recvd[len(QUESTION):]
 
132
                sys.stdout.write(recvd)
 
133
                raw = sys.stdin.readline() or b'n'
 
134
            else:
 
135
                sys.stdout.write(recvd)
 
136
                raw = b''
 
137
                try:
 
138
                    raw = raw_input(PROMPT) + b'\n'
 
139
                except (EOFError, KeyboardInterrupt):
 
140
                    pass
 
141
                if not raw:
 
142
                    raw = b'quit\n'
 
143
            eintr_retry_call(sock.send, raw)
 
144
    except KeyboardInterrupt:
 
145
        pass
 
146
 
 
147
if __name__ == '__main__':
 
148
    cli()