remotePythonConsole.py
2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#remotePythonConsole.py
#A part of NonVisual Desktop Access (NVDA)
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
#Copyright (C) 2011 NV Access Inc
"""Provides an interactive Python console run inside NVDA which can be accessed via TCP.
To use, call L{initialize} to start the server.
Then, connect to it using TCP port L{PORT}.
The server will only handle one connection at a time.
"""
import threading
import SocketServer
import wx
import pythonConsole
from logHandler import log
#: The TCP port on which the server will run.
#: @type: int
PORT = 6832
server = None
class RequestHandler(SocketServer.StreamRequestHandler):
def setPrompt(self, prompt):
if not self._keepRunning:
# We're about to exit, so don't output the prompt.
return
self.wfile.write(prompt + " ")
def exit(self):
self._keepRunning = False
def execute(self, line):
self.console.push(line)
# Notify handle() that the line has finished executing.
self._execDoneEvt.set()
def handle(self):
# #3126: Remove the default socket timeout.
# We can't use the class timeout attribute because None means don't set a timeout.
self.connection.settimeout(None)
self._keepRunning = True
try:
self.wfile.write("NVDA Remote Python Console\n")
self.console = pythonConsole.PythonConsole(outputFunc=self.wfile.write, setPromptFunc=self.setPrompt, exitFunc=self.exit)
self.console.namespace.update({
"snap": self.console.updateNamespaceSnapshotVars,
"rmSnap": self.console.removeNamespaceSnapshotVars,
})
self._execDoneEvt = threading.Event()
while self._keepRunning:
line = self.rfile.readline()
if not line:
break
line = line.rstrip("\r\n")
# Execute in the main thread.
wx.CallAfter(self.execute, line)
# Wait until the line has finished executing before retrieving the next.
self._execDoneEvt.wait()
self._execDoneEvt.clear()
except:
log.exception("Error handling remote Python console request")
finally:
# Clean up the console.
self.console = None
def initialize():
global server
server = SocketServer.TCPServer(("", PORT), RequestHandler)
server.daemon_threads = True
thread = threading.Thread(target=server.serve_forever)
thread.daemon = True
thread.start()
def terminate():
global server
server.shutdown()
server = None