DebugClients/Python/DebugClientBase.py

changeset 2987
c99695c0f13a
parent 2953
703452a2876f
child 3021
801289962f4e
equal deleted inserted replaced
2986:cd4e2cab7eb2 2987:c99695c0f13a
27 from FlexCompleter import Completer 27 from FlexCompleter import Completer
28 28
29 29
30 DebugClientInstance = None 30 DebugClientInstance = None
31 31
32 ################################################################################ 32 ###############################################################################
33 33
34 34
35 def DebugClientRawInput(prompt="", echo=1): 35 def DebugClientRawInput(prompt="", echo=1):
36 """ 36 """
37 Replacement for the standard raw_input builtin. 37 Replacement for the standard raw_input builtin.
54 except (AttributeError, KeyError): 54 except (AttributeError, KeyError):
55 import __main__ 55 import __main__
56 DebugClientOrigRawInput = __main__.__builtins__.__dict__['raw_input'] 56 DebugClientOrigRawInput = __main__.__builtins__.__dict__['raw_input']
57 __main__.__builtins__.__dict__['raw_input'] = DebugClientRawInput 57 __main__.__builtins__.__dict__['raw_input'] = DebugClientRawInput
58 58
59 ################################################################################ 59 ###############################################################################
60 60
61 61
62 def DebugClientInput(prompt=""): 62 def DebugClientInput(prompt=""):
63 """ 63 """
64 Replacement for the standard input builtin. 64 Replacement for the standard input builtin.
80 except (AttributeError, KeyError): 80 except (AttributeError, KeyError):
81 import __main__ 81 import __main__
82 DebugClientOrigInput = __main__.__builtins__.__dict__['input'] 82 DebugClientOrigInput = __main__.__builtins__.__dict__['input']
83 __main__.__builtins__.__dict__['input'] = DebugClientInput 83 __main__.__builtins__.__dict__['input'] = DebugClientInput
84 84
85 ################################################################################ 85 ###############################################################################
86 86
87 87
88 def DebugClientFork(): 88 def DebugClientFork():
89 """ 89 """
90 Replacement for the standard os.fork(). 90 Replacement for the standard os.fork().
99 # use our own fork(). 99 # use our own fork().
100 if 'fork' in dir(os): 100 if 'fork' in dir(os):
101 DebugClientOrigFork = os.fork 101 DebugClientOrigFork = os.fork
102 os.fork = DebugClientFork 102 os.fork = DebugClientFork
103 103
104 ################################################################################ 104 ###############################################################################
105 105
106 106
107 def DebugClientClose(fd): 107 def DebugClientClose(fd):
108 """ 108 """
109 Replacement for the standard os.close(fd). 109 Replacement for the standard os.close(fd).
118 # use our own close(). 118 # use our own close().
119 if 'close' in dir(os): 119 if 'close' in dir(os):
120 DebugClientOrigClose = os.close 120 DebugClientOrigClose = os.close
121 os.close = DebugClientClose 121 os.close = DebugClientClose
122 122
123 ################################################################################ 123 ###############################################################################
124 124
125 125
126 def DebugClientSetRecursionLimit(limit): 126 def DebugClientSetRecursionLimit(limit):
127 """ 127 """
128 Replacement for the standard sys.setrecursionlimit(limit). 128 Replacement for the standard sys.setrecursionlimit(limit).
137 if 'setrecursionlimit' in dir(sys): 137 if 'setrecursionlimit' in dir(sys):
138 DebugClientOrigSetRecursionLimit = sys.setrecursionlimit 138 DebugClientOrigSetRecursionLimit = sys.setrecursionlimit
139 sys.setrecursionlimit = DebugClientSetRecursionLimit 139 sys.setrecursionlimit = DebugClientSetRecursionLimit
140 DebugClientSetRecursionLimit(sys.getrecursionlimit()) 140 DebugClientSetRecursionLimit(sys.getrecursionlimit())
141 141
142 ################################################################################ 142 ###############################################################################
143 143
144 144
145 class DebugClientBase(object): 145 class DebugClientBase(object):
146 """ 146 """
147 Class implementing the client side of the debugger. 147 Class implementing the client side of the debugger.
148 148
149 It provides access to the Python interpeter from a debugger running in another 149 It provides access to the Python interpeter from a debugger running in
150 process whether or not the Qt event loop is running. 150 another process whether or not the Qt event loop is running.
151 151
152 The protocol between the debugger and the client assumes that there will be 152 The protocol between the debugger and the client assumes that there will be
153 a single source of debugger commands and a single source of Python 153 a single source of debugger commands and a single source of Python
154 statements. Commands and statement are always exactly one line and may be 154 statements. Commands and statement are always exactly one line and may be
155 interspersed. 155 interspersed.
158 debugger and then sends a series of one line commands. A command is either 158 debugger and then sends a series of one line commands. A command is either
159 >Load<, >Step<, >StepInto<, ... or a Python statement. 159 >Load<, >Step<, >StepInto<, ... or a Python statement.
160 See DebugProtocol.py for a listing of valid protocol tokens. 160 See DebugProtocol.py for a listing of valid protocol tokens.
161 161
162 A Python statement consists of the statement to execute, followed (in a 162 A Python statement consists of the statement to execute, followed (in a
163 separate line) by >OK?<. If the statement was incomplete then the response 163 separate line) by >OK?<. If the statement was incomplete then the
164 is >Continue<. If there was an exception then the response is 164 response is >Continue<. If there was an exception then the response
165 >Exception<. 165 is >Exception<. Otherwise the response is >OK<. The reason
166 Otherwise the response is >OK<. The reason for the >OK?< part is to 166 for the >OK?< part is to provide a sentinal (ie. the responding
167 provide a sentinal (ie. the responding >OK<) after any possible output as a 167 >OK<) after any possible output as a result of executing the command.
168 result of executing the command.
169 168
170 The client may send any other lines at any other time which should be 169 The client may send any other lines at any other time which should be
171 interpreted as program output. 170 interpreted as program output.
172 171
173 If the debugger closes the session there is no response from the client. 172 If the debugger closes the session there is no response from the client.
174 The client may close the session at any time as a result of the script 173 The client may close the session at any time as a result of the script
175 being debugged closing or crashing. 174 being debugged closing or crashing.
176 175
177 <b>Note</b>: This class is meant to be subclassed by individual DebugClient classes. 176 <b>Note</b>: This class is meant to be subclassed by individual
178 Do not instantiate it directly. 177 DebugClient classes. Do not instantiate it directly.
179 """ 178 """
180 clientCapabilities = DebugClientCapabilities.HasAll 179 clientCapabilities = DebugClientCapabilities.HasAll
181 180
182 def __init__(self): 181 def __init__(self):
183 """ 182 """
191 # debugger 190 # debugger
192 191
193 # dictionary of all threads running 192 # dictionary of all threads running
194 self.threads = {} 193 self.threads = {}
195 194
196 # the "current" thread, basically the thread we are at a breakpoint for. 195 # the "current" thread, basically the thread we are at a
196 # breakpoint for.
197 self.currentThread = self 197 self.currentThread = self
198 198
199 # special objects representing the main scripts thread and frame 199 # special objects representing the main scripts thread and frame
200 self.mainThread = self 200 self.mainThread = self
201 self.mainFrame = None 201 self.mainFrame = None
293 started mainthread of the app and the rest of the args are ignored. 293 started mainthread of the app and the rest of the args are ignored.
294 294
295 This is just an empty function and is overridden in the threaded 295 This is just an empty function and is overridden in the threaded
296 debugger. 296 debugger.
297 297
298 @param target the start function of the target thread (i.e. the user code) 298 @param target the start function of the target thread (i.e. the user
299 code)
299 @param args arguments to pass to target 300 @param args arguments to pass to target
300 @param kwargs keyword arguments to pass to target 301 @param kwargs keyword arguments to pass to target
301 @param mainThread non-zero, if we are attaching to the already 302 @param mainThread non-zero, if we are attaching to the already
302 started mainthread of the app 303 started mainthread of the app
303 """ 304 """
307 def __dumpThreadList(self): 308 def __dumpThreadList(self):
308 """ 309 """
309 Public method to send the list of threads. 310 Public method to send the list of threads.
310 """ 311 """
311 threadList = [] 312 threadList = []
312 if self.threads and self.currentThread: # indication for the threaded debugger 313 if self.threads and self.currentThread:
314 # indication for the threaded debugger
313 currentId = self.currentThread.get_ident() 315 currentId = self.currentThread.get_ident()
314 for t in self.threads.values(): 316 for t in self.threads.values():
315 d = {} 317 d = {}
316 d["id"] = t.get_ident() 318 d["id"] = t.get_ident()
317 d["name"] = t.get_name() 319 d["name"] = t.get_name()
334 336
335 @param prompt the prompt to be shown (string) 337 @param prompt the prompt to be shown (string)
336 @param echo Flag indicating echoing of the input (boolean) 338 @param echo Flag indicating echoing of the input (boolean)
337 @return the entered string 339 @return the entered string
338 """ 340 """
339 self.write("%s%s\n" % (DebugProtocol.ResponseRaw, unicode((prompt, echo)))) 341 self.write("%s%s\n" % (DebugProtocol.ResponseRaw,
342 unicode((prompt, echo))))
340 self.inRawMode = 1 343 self.inRawMode = 1
341 self.eventLoop(True) 344 self.eventLoop(True)
342 return self.rawLine 345 return self.rawLine
343 346
344 def input(self, prompt): 347 def input(self, prompt):
358 """ 361 """
359 self.pendingResponse = DebugProtocol.ResponseException 362 self.pendingResponse = DebugProtocol.ResponseException
360 363
361 def sessionClose(self, exit=1): 364 def sessionClose(self, exit=1):
362 """ 365 """
363 Public method to close the session with the debugger and optionally terminate. 366 Public method to close the session with the debugger and optionally
367 terminate.
364 368
365 @param exit flag indicating to terminate (boolean) 369 @param exit flag indicating to terminate (boolean)
366 """ 370 """
367 try: 371 try:
368 self.set_quit() 372 self.set_quit()
386 390
387 def handleLine(self, line): 391 def handleLine(self, line):
388 """ 392 """
389 Public method to handle the receipt of a complete line. 393 Public method to handle the receipt of a complete line.
390 394
391 It first looks for a valid protocol token at the start of the line. Thereafter 395 It first looks for a valid protocol token at the start of the line.
392 it trys to execute the lines accumulated so far. 396 Thereafter it trys to execute the lines accumulated so far.
393 397
394 @param line the received line 398 @param line the received line
395 """ 399 """
396 # Remove any newline. 400 # Remove any newline.
397 if line[-1] == '\n': 401 if line[-1] == '\n':
424 tid = eval(arg) 428 tid = eval(arg)
425 if tid in self.threads: 429 if tid in self.threads:
426 self.setCurrentThread(tid) 430 self.setCurrentThread(tid)
427 self.write(DebugProtocol.ResponseThreadSet + '\n') 431 self.write(DebugProtocol.ResponseThreadSet + '\n')
428 stack = self.currentThread.getStack() 432 stack = self.currentThread.getStack()
429 self.write('%s%s\n' % (DebugProtocol.ResponseStack, unicode(stack))) 433 self.write('%s%s\n' % (DebugProtocol.ResponseStack,
434 unicode(stack)))
430 return 435 return
431 436
432 if cmd == DebugProtocol.RequestStep: 437 if cmd == DebugProtocol.RequestStep:
433 self.currentThread.step(1) 438 self.currentThread.step(1)
434 self.eventExit = 1 439 self.eventExit = 1
469 else: 474 else:
470 callTraceEnabled = False 475 callTraceEnabled = False
471 if self.debugging: 476 if self.debugging:
472 self.callTraceEnabled = callTraceEnabled 477 self.callTraceEnabled = callTraceEnabled
473 else: 478 else:
474 self.__newCallTraceEnabled = callTraceEnabled # remember for later 479 self.__newCallTraceEnabled = callTraceEnabled
480 # remember for later
475 return 481 return
476 482
477 if cmd == DebugProtocol.RequestEnv: 483 if cmd == DebugProtocol.RequestEnv:
478 env = eval(arg) 484 env = eval(arg)
479 for key, value in env.items(): 485 for key, value in env.items():
510 516
511 # set the system exception handling function to ensure, that 517 # set the system exception handling function to ensure, that
512 # we report on all unhandled exceptions 518 # we report on all unhandled exceptions
513 sys.excepthook = self.__unhandled_exception 519 sys.excepthook = self.__unhandled_exception
514 520
515 # clear all old breakpoints, they'll get set after we have started 521 # clear all old breakpoints, they'll get set after we
522 # have started
516 self.mainThread.clear_all_breaks() 523 self.mainThread.clear_all_breaks()
517 524
518 self.mainThread.tracePython = tracePython 525 self.mainThread.tracePython = tracePython
519 526
520 # This will eventually enter a local event loop. 527 # This will eventually enter a local event loop.
521 # Note the use of backquotes to cause a repr of self.running. The 528 # Note the use of backquotes to cause a repr of self.running.
522 # need for this is on Windows os where backslash is the path separator. 529 # The need for this is on Windows os where backslash is the
523 # They will get inadvertantly stripped away during the eval causing 530 # path separator. They will get inadvertantly stripped away
524 # IOErrors, if self.running is passed as a normal str. 531 # during the eval causing IOErrors, if self.running is passed
532 # as a normal str.
525 self.debugMod.__dict__['__file__'] = self.running 533 self.debugMod.__dict__['__file__'] = self.running
526 sys.modules['__main__'] = self.debugMod 534 sys.modules['__main__'] = self.debugMod
527 self.callTraceEnabled = self.__newCallTraceEnabled 535 self.callTraceEnabled = self.__newCallTraceEnabled
528 res = self.mainThread.run('execfile(' + repr(self.running) + ')', 536 res = self.mainThread.run(
529 self.debugMod.__dict__) 537 'execfile(' + repr(self.running) + ')',
538 self.debugMod.__dict__)
530 self.progTerminated(res) 539 self.progTerminated(res)
531 return 540 return
532 541
533 if cmd == DebugProtocol.RequestRun: 542 if cmd == DebugProtocol.RequestRun:
534 sys.argv = [] 543 sys.argv = []
661 else: 670 else:
662 try: 671 try:
663 compile(cond, '<string>', 'eval') 672 compile(cond, '<string>', 'eval')
664 except SyntaxError: 673 except SyntaxError:
665 self.write('%s%s,%d\n' % \ 674 self.write('%s%s,%d\n' % \
666 (DebugProtocol.ResponseBPConditionError, fn, line)) 675 (DebugProtocol.ResponseBPConditionError, fn,
676 line))
667 return 677 return
668 self.mainThread.set_break(fn, line, temporary, cond) 678 self.mainThread.set_break(fn, line, temporary, cond)
669 else: 679 else:
670 self.mainThread.clear_break(fn, line) 680 self.mainThread.clear_break(fn, line)
671 681
739 749
740 return 750 return
741 751
742 if cmd == DebugProtocol.RequestEval: 752 if cmd == DebugProtocol.RequestEval:
743 try: 753 try:
744 value = eval(arg, self.currentThread.getCurrentFrame().f_globals, 754 value = eval(
745 self.currentThread.getCurrentFrameLocals()) 755 arg, self.currentThread.getCurrentFrame().f_globals,
756 self.currentThread.getCurrentFrameLocals())
746 except: 757 except:
747 # Report the exception and the traceback 758 # Report the exception and the traceback
748 try: 759 try:
749 type, value, tb = sys.exc_info() 760 type, value, tb = sys.exc_info()
750 sys.last_type = type 761 sys.last_type = type
804 unicode(("Python %s" % sys.version, socket.gethostname(), 815 unicode(("Python %s" % sys.version, socket.gethostname(),
805 self.variant)))) 816 self.variant))))
806 return 817 return
807 818
808 if cmd == DebugProtocol.RequestCapabilities: 819 if cmd == DebugProtocol.RequestCapabilities:
809 self.write('%s%d, "Python"\n' % (DebugProtocol.ResponseCapabilities, 820 self.write('%s%d, "Python"\n' % (
821 DebugProtocol.ResponseCapabilities,
810 self.__clientCapabilities())) 822 self.__clientCapabilities()))
811 return 823 return
812 824
813 if cmd == DebugProtocol.RequestCompletion: 825 if cmd == DebugProtocol.RequestCompletion:
814 self.__completionList(arg) 826 self.__completionList(arg)
906 try: 918 try:
907 code = self.compile_command(self.buffer, self.readstream.name) 919 code = self.compile_command(self.buffer, self.readstream.name)
908 except (OverflowError, SyntaxError, ValueError): 920 except (OverflowError, SyntaxError, ValueError):
909 # Report the exception 921 # Report the exception
910 sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() 922 sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info()
911 map(self.write, traceback.format_exception_only(sys.last_type, sys.last_value)) 923 map(self.write, traceback.format_exception_only(
924 sys.last_type, sys.last_value))
912 self.buffer = '' 925 self.buffer = ''
913 else: 926 else:
914 if code is None: 927 if code is None:
915 self.pendingResponse = DebugProtocol.ResponseContinue 928 self.pendingResponse = DebugProtocol.ResponseContinue
916 else: 929 else:
936 frmnr = self.framenr 949 frmnr = self.framenr
937 while cf is not None and frmnr > 0: 950 while cf is not None and frmnr > 0:
938 cf = cf.f_back 951 cf = cf.f_back
939 frmnr -= 1 952 frmnr -= 1
940 _globals = cf.f_globals 953 _globals = cf.f_globals
941 _locals = self.currentThread.getCurrentFrameLocals() 954 _locals = \
955 self.currentThread.getCurrentFrameLocals()
942 # reset sys.stdout to our redirector (unconditionally) 956 # reset sys.stdout to our redirector (unconditionally)
943 if "sys" in _globals: 957 if "sys" in _globals:
944 __stdout = _globals["sys"].stdout 958 __stdout = _globals["sys"].stdout
945 _globals["sys"].stdout = self.writestream 959 _globals["sys"].stdout = self.writestream
946 exec code in _globals, _locals 960 exec code in _globals, _locals
985 del sys.modules['PyProfile'] 999 del sys.modules['PyProfile']
986 except KeyError: 1000 except KeyError:
987 pass 1001 pass
988 return self.clientCapabilities 1002 return self.clientCapabilities
989 except ImportError: 1003 except ImportError:
990 return self.clientCapabilities & ~DebugClientCapabilities.HasProfiler 1004 return (self.clientCapabilities &
1005 ~DebugClientCapabilities.HasProfiler)
991 1006
992 def write(self, s): 1007 def write(self, s):
993 """ 1008 """
994 Public method to write data to the output stream. 1009 Public method to write data to the output stream.
995 1010
1093 It opens a network connection to the debugger, connects it to stdin, 1108 It opens a network connection to the debugger, connects it to stdin,
1094 stdout and stderr and saves these file objects in case the application 1109 stdout and stderr and saves these file objects in case the application
1095 being debugged redirects them itself. 1110 being debugged redirects them itself.
1096 1111
1097 @param port the port number to connect to (int) 1112 @param port the port number to connect to (int)
1098 @param remoteAddress the network address of the debug server host (string) 1113 @param remoteAddress the network address of the debug server host
1099 @param redirect flag indicating redirection of stdin, stdout and stderr (boolean) 1114 (string)
1100 """ 1115 @param redirect flag indicating redirection of stdin, stdout and
1101 if remoteAddress is None: # default: 127.0.0.1 1116 stderr (boolean)
1117 """
1118 if remoteAddress is None: # default: 127.0.0.1
1102 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1119 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1103 sock.connect((DebugProtocol.DebugAddress, port)) 1120 sock.connect((DebugProtocol.DebugAddress, port))
1104 else: 1121 else:
1105 if "@@i" in remoteAddress: 1122 if "@@i" in remoteAddress:
1106 remoteAddress, index = remoteAddress.split("@@i") 1123 remoteAddress, index = remoteAddress.split("@@i")
1107 else: 1124 else:
1108 index = 0 1125 index = 0
1109 if ":" in remoteAddress: # IPv6 1126 if ":" in remoteAddress: # IPv6
1110 sockaddr = socket.getaddrinfo( 1127 sockaddr = socket.getaddrinfo(
1111 remoteAddress, port, 0, 0, socket.SOL_TCP)[0][-1] 1128 remoteAddress, port, 0, 0, socket.SOL_TCP)[0][-1]
1112 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 1129 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
1113 sockaddr = sockaddr[:-1] + (int(index),) 1130 sockaddr = sockaddr[:-1] + (int(index),)
1114 sock.connect(sockaddr) 1131 sock.connect(sockaddr)
1115 else: # IPv4 1132 else: # IPv4
1116 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1133 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1117 sock.connect((remoteAddress, port)) 1134 sock.connect((remoteAddress, port))
1118 1135
1119 self.readstream = AsyncFile(sock, sys.stdin.mode, sys.stdin.name) 1136 self.readstream = AsyncFile(sock, sys.stdin.mode, sys.stdin.name)
1120 self.writestream = AsyncFile(sock, sys.stdout.mode, sys.stdout.name) 1137 self.writestream = AsyncFile(sock, sys.stdout.mode, sys.stdout.name)
1183 def shouldSkip(self, fn): 1200 def shouldSkip(self, fn):
1184 """ 1201 """
1185 Public method to check if a file should be skipped. 1202 Public method to check if a file should be skipped.
1186 1203
1187 @param fn filename to be checked 1204 @param fn filename to be checked
1188 @return non-zero if fn represents a file we are 'skipping', zero otherwise. 1205 @return non-zero if fn represents a file we are 'skipping',
1206 zero otherwise.
1189 """ 1207 """
1190 if self.mainThread.tracePython: # trace into Python library 1208 if self.mainThread.tracePython: # trace into Python library
1191 return 0 1209 return 0
1192 1210
1193 # Eliminate anything that is part of the Python installation. 1211 # Eliminate anything that is part of the Python installation.
1235 1253
1236 def __dumpVariables(self, frmnr, scope, filter): 1254 def __dumpVariables(self, frmnr, scope, filter):
1237 """ 1255 """
1238 Private method to return the variables of a frame to the debug server. 1256 Private method to return the variables of a frame to the debug server.
1239 1257
1240 @param frmnr distance of frame reported on. 0 is the current frame (int) 1258 @param frmnr distance of frame reported on. 0 is the current frame
1259 (int)
1241 @param scope 1 to report global variables, 0 for local variables (int) 1260 @param scope 1 to report global variables, 0 for local variables (int)
1242 @param filter the indices of variable types to be filtered (list of int) 1261 @param filter the indices of variable types to be filtered (list of
1262 int)
1243 """ 1263 """
1244 if self.currentThread is None: 1264 if self.currentThread is None:
1245 return 1265 return
1246 1266
1247 if scope == 0: 1267 if scope == 0:
1270 keylist = dict.keys() 1290 keylist = dict.keys()
1271 1291
1272 vlist = self.__formatVariablesList(keylist, dict, scope, filter) 1292 vlist = self.__formatVariablesList(keylist, dict, scope, filter)
1273 varlist.extend(vlist) 1293 varlist.extend(vlist)
1274 1294
1275 self.write('%s%s\n' % (DebugProtocol.ResponseVariables, unicode(varlist))) 1295 self.write('%s%s\n' % (
1296 DebugProtocol.ResponseVariables, unicode(varlist)))
1276 1297
1277 def __dumpVariable(self, var, frmnr, scope, filter): 1298 def __dumpVariable(self, var, frmnr, scope, filter):
1278 """ 1299 """
1279 Private method to return the variables of a frame to the debug server. 1300 Private method to return the variables of a frame to the debug server.
1280 1301
1281 @param var list encoded name of the requested variable (list of strings) 1302 @param var list encoded name of the requested variable
1282 @param frmnr distance of frame reported on. 0 is the current frame (int) 1303 (list of strings)
1304 @param frmnr distance of frame reported on. 0 is the current frame
1305 (int)
1283 @param scope 1 to report global variables, 0 for local variables (int) 1306 @param scope 1 to report global variables, 0 for local variables (int)
1284 @param filter the indices of variable types to be filtered (list of int) 1307 @param filter the indices of variable types to be filtered
1308 (list of int)
1285 """ 1309 """
1286 if self.currentThread is None: 1310 if self.currentThread is None:
1287 return 1311 return
1288 1312
1289 f = self.currentThread.getCurrentFrame() 1313 f = self.currentThread.getCurrentFrame()
1387 ndict.update(mdict) # __IGNORE_WARNING__ 1411 ndict.update(mdict) # __IGNORE_WARNING__
1388 exec 'obj = dict%s' % access 1412 exec 'obj = dict%s' % access
1389 if "PyQt4." in str(type(obj)): 1413 if "PyQt4." in str(type(obj)):
1390 qtVariable = True 1414 qtVariable = True
1391 qvar = obj 1415 qvar = obj
1392 qvtype = ("%s" % type(qvar))[1:-1].split()[1][1:-1] 1416 qvtype = ("%s" % type(qvar))[1:-1]\
1417 .split()[1][1:-1]
1393 except: 1418 except:
1394 pass 1419 pass
1395 try: 1420 try:
1396 exec 'mcdict = dict%s.__class__.__dict__' % access 1421 exec 'mcdict = dict%s.__class__.__dict__' % access
1397 ndict.update(mcdict) # __IGNORE_WARNING__ 1422 ndict.update(mcdict) # __IGNORE_WARNING__
1412 exec 'obj = dict%s' % access 1437 exec 'obj = dict%s' % access
1413 access = "" 1438 access = ""
1414 if "PyQt4." in str(type(obj)): 1439 if "PyQt4." in str(type(obj)):
1415 qtVariable = True 1440 qtVariable = True
1416 qvar = obj 1441 qvar = obj
1417 qvtype = ("%s" % type(qvar))[1:-1].split()[1][1:-1] 1442 qvtype = ("%s" % type(qvar))[1:-1]\
1443 .split()[1][1:-1]
1418 except: 1444 except:
1419 pass 1445 pass
1420 else: 1446 else:
1421 try: 1447 try:
1422 ndict.update(dict[var[i]].__dict__) 1448 ndict.update(dict[var[i]].__dict__)
1424 del rvar[0] 1450 del rvar[0]
1425 obj = dict[var[i]] 1451 obj = dict[var[i]]
1426 if "PyQt4." in str(type(obj)): 1452 if "PyQt4." in str(type(obj)):
1427 qtVariable = True 1453 qtVariable = True
1428 qvar = obj 1454 qvar = obj
1429 qvtype = ("%s" % type(qvar))[1:-1].split()[1][1:-1] 1455 qvtype = ("%s" % type(qvar))[1:-1]\
1456 .split()[1][1:-1]
1430 except: 1457 except:
1431 pass 1458 pass
1432 try: 1459 try:
1433 cdict = {} 1460 cdict = {}
1434 slv = dict[var[i]].__slots__ 1461 slv = dict[var[i]].__slots__
1440 ndict.update(cdict) 1467 ndict.update(cdict)
1441 obj = dict[var[i]] 1468 obj = dict[var[i]]
1442 if "PyQt4." in str(type(obj)): 1469 if "PyQt4." in str(type(obj)):
1443 qtVariable = True 1470 qtVariable = True
1444 qvar = obj 1471 qvar = obj
1445 qvtype = ("%s" % type(qvar))[1:-1].split()[1][1:-1] 1472 qvtype = ("%s" % type(qvar))[1:-1]\
1473 .split()[1][1:-1]
1446 except: 1474 except:
1447 pass 1475 pass
1448 odict = dict 1476 odict = dict
1449 dict = ndict 1477 dict = ndict
1450 i += 1 1478 i += 1
1493 dict = dict[dictkeys[0]] 1521 dict = dict[dictkeys[0]]
1494 if isDict: 1522 if isDict:
1495 dictkeys = dict.keys() 1523 dictkeys = dict.keys()
1496 else: 1524 else:
1497 dictkeys = range(len(dict)) 1525 dictkeys = range(len(dict))
1498 vlist = self.__formatVariablesList(dictkeys, dict, scope, filter, 1526 vlist = self.__formatVariablesList(
1499 formatSequences) 1527 dictkeys, dict, scope, filter, formatSequences)
1500 varlist.extend(vlist) 1528 varlist.extend(vlist)
1501 1529
1502 if obj is not None and not formatSequences: 1530 if obj is not None and not formatSequences:
1503 try: 1531 try:
1504 if unicode(repr(obj)).startswith('{'): 1532 if unicode(repr(obj)).startswith('{'):
1508 elif unicode(repr(obj)).startswith('('): 1536 elif unicode(repr(obj)).startswith('('):
1509 varlist.append(('...', 'tuple', "%d" % len(obj))) 1537 varlist.append(('...', 'tuple', "%d" % len(obj)))
1510 except: 1538 except:
1511 pass 1539 pass
1512 1540
1513 self.write('%s%s\n' % (DebugProtocol.ResponseVariable, unicode(varlist))) 1541 self.write('%s%s\n' % (
1542 DebugProtocol.ResponseVariable, unicode(varlist)))
1514 1543
1515 def __formatQt4Variable(self, value, vtype): 1544 def __formatQt4Variable(self, value, vtype):
1516 """ 1545 """
1517 Private method to produce a formated output of a simple Qt4/Qt5 type. 1546 Private method to produce a formated output of a simple Qt4/Qt5 type.
1518 1547
1564 r, g, b, a = value.getRgb() 1593 r, g, b, a = value.getRgb()
1565 varlist.append(("rgb", "int", "%d, %d, %d, %d" % (r, g, b, a))) 1594 varlist.append(("rgb", "int", "%d, %d, %d, %d" % (r, g, b, a)))
1566 h, s, v, a = value.getHsv() 1595 h, s, v, a = value.getHsv()
1567 varlist.append(("hsv", "int", "%d, %d, %d, %d" % (h, s, v, a))) 1596 varlist.append(("hsv", "int", "%d, %d, %d, %d" % (h, s, v, a)))
1568 c, m, y, k, a = value.getCmyk() 1597 c, m, y, k, a = value.getCmyk()
1569 varlist.append(("cmyk", "int", "%d, %d, %d, %d, %d" % (c, m, y, k, a))) 1598 varlist.append(
1599 ("cmyk", "int", "%d, %d, %d, %d, %d" % (c, m, y, k, a)))
1570 elif qttype == 'QDate': 1600 elif qttype == 'QDate':
1571 varlist.append(("", "QDate", "%s" % value.toString())) 1601 varlist.append(("", "QDate", "%s" % value.toString()))
1572 elif qttype == 'QTime': 1602 elif qttype == 'QTime':
1573 varlist.append(("", "QTime", "%s" % value.toString())) 1603 varlist.append(("", "QTime", "%s" % value.toString()))
1574 elif qttype == 'QDateTime': 1604 elif qttype == 'QDateTime':
1575 varlist.append(("", "QDateTime", "%s" % value.toString())) 1605 varlist.append(("", "QDateTime", "%s" % value.toString()))
1576 elif qttype == 'QDir': 1606 elif qttype == 'QDir':
1577 varlist.append(("path", "str", "%s" % value.path())) 1607 varlist.append(("path", "str", "%s" % value.path()))
1578 varlist.append(("absolutePath", "str", "%s" % value.absolutePath())) 1608 varlist.append(
1579 varlist.append(("canonicalPath", "str", "%s" % value.canonicalPath())) 1609 ("absolutePath", "str", "%s" % value.absolutePath()))
1610 varlist.append(
1611 ("canonicalPath", "str", "%s" % value.canonicalPath()))
1580 elif qttype == 'QFile': 1612 elif qttype == 'QFile':
1581 varlist.append(("fileName", "str", "%s" % value.fileName())) 1613 varlist.append(("fileName", "str", "%s" % value.fileName()))
1582 elif qttype == 'QFont': 1614 elif qttype == 'QFont':
1583 varlist.append(("family", "str", "%s" % value.family())) 1615 varlist.append(("family", "str", "%s" % value.family()))
1584 varlist.append(("pointSize", "int", "%d" % value.pointSize())) 1616 varlist.append(("pointSize", "int", "%d" % value.pointSize()))
1596 elif qttype == 'QModelIndex': 1628 elif qttype == 'QModelIndex':
1597 varlist.append(("valid", "bool", "%s" % value.isValid())) 1629 varlist.append(("valid", "bool", "%s" % value.isValid()))
1598 if value.isValid(): 1630 if value.isValid():
1599 varlist.append(("row", "int", "%s" % value.row())) 1631 varlist.append(("row", "int", "%s" % value.row()))
1600 varlist.append(("column", "int", "%s" % value.column())) 1632 varlist.append(("column", "int", "%s" % value.column()))
1601 varlist.append(("internalId", "int", "%s" % value.internalId())) 1633 varlist.append(
1634 ("internalId", "int", "%s" % value.internalId()))
1602 varlist.append(("internalPointer", "void *", "%s" % \ 1635 varlist.append(("internalPointer", "void *", "%s" % \
1603 value.internalPointer())) 1636 value.internalPointer()))
1604 elif qttype == 'QRegExp': 1637 elif qttype == 'QRegExp':
1605 varlist.append(("pattern", "str", "%s" % value.pattern())) 1638 varlist.append(("pattern", "str", "%s" % value.pattern()))
1606 1639
1609 varlist.append(("name", "str", "%s" % value.objectName())) 1642 varlist.append(("name", "str", "%s" % value.objectName()))
1610 varlist.append(("text", "str", "%s" % value.text())) 1643 varlist.append(("text", "str", "%s" % value.text()))
1611 varlist.append(("icon text", "str", "%s" % value.iconText())) 1644 varlist.append(("icon text", "str", "%s" % value.iconText()))
1612 varlist.append(("tooltip", "str", "%s" % value.toolTip())) 1645 varlist.append(("tooltip", "str", "%s" % value.toolTip()))
1613 varlist.append(("whatsthis", "str", "%s" % value.whatsThis())) 1646 varlist.append(("whatsthis", "str", "%s" % value.whatsThis()))
1614 varlist.append(("shortcut", "str", "%s" % value.shortcut().toString())) 1647 varlist.append(
1648 ("shortcut", "str", "%s" % value.shortcut().toString()))
1615 elif qttype == 'QKeySequence': 1649 elif qttype == 'QKeySequence':
1616 varlist.append(("value", "", "%s" % value.toString())) 1650 varlist.append(("value", "", "%s" % value.toString()))
1617 1651
1618 # XML stuff 1652 # XML stuff
1619 elif qttype == 'QDomAttr': 1653 elif qttype == 'QDomAttr':
1631 elif qttype == 'QDomText': 1665 elif qttype == 'QDomText':
1632 varlist.append(("data", "str", "%s" % value.data())) 1666 varlist.append(("data", "str", "%s" % value.data()))
1633 1667
1634 # Networking stuff 1668 # Networking stuff
1635 elif qttype == 'QHostAddress': 1669 elif qttype == 'QHostAddress':
1636 varlist.append(("address", "QHostAddress", "%s" % value.toString())) 1670 varlist.append(
1671 ("address", "QHostAddress", "%s" % value.toString()))
1637 1672
1638 return varlist 1673 return varlist
1639 1674
1640 def __formatVariablesList(self, keylist, dict, scope, filter=[], 1675 def __formatVariablesList(self, keylist, dict, scope, filter=[],
1641 formatSequences=0): 1676 formatSequences=0):
1642 """ 1677 """
1643 Private method to produce a formated variables list. 1678 Private method to produce a formated variables list.
1644 1679
1645 The dictionary passed in to it is scanned. Variables are 1680 The dictionary passed in to it is scanned. Variables are
1646 only added to the list, if their type is not contained 1681 only added to the list, if their type is not contained
1647 in the filter list and their name doesn't match any of the filter expressions. 1682 in the filter list and their name doesn't match any of
1648 The formated variables list (a list of tuples of 3 values) is returned. 1683 the filter expressions. The formated variables list (a list of tuples
1684 of 3 values) is returned.
1649 1685
1650 @param keylist keys of the dictionary 1686 @param keylist keys of the dictionary
1651 @param dict the dictionary to be scanned 1687 @param dict the dictionary to be scanned
1652 @param scope 1 to filter using the globals filter, 0 using the locals 1688 @param scope 1 to filter using the globals filter, 0 using the locals
1653 filter (int). 1689 filter (int).
1654 Variables are only added to the list, if their name do not match any of the 1690 Variables are only added to the list, if their name do not match
1655 filter expressions. 1691 any of the filter expressions.
1656 @param filter the indices of variable types to be filtered. Variables are 1692 @param filter the indices of variable types to be filtered. Variables
1657 only added to the list, if their type is not contained in the filter 1693 are only added to the list, if their type is not contained in the
1658 list. 1694 filter list.
1659 @param formatSequences flag indicating, that sequence or dictionary variables 1695 @param formatSequences flag indicating, that sequence or dictionary
1660 should be formatted. If it is 0 (or false), just the number of items contained 1696 variables should be formatted. If it is 0 (or false), just the
1661 in these variables is returned. (boolean) 1697 number of items contained in these variables is returned. (boolean)
1662 @return A tuple consisting of a list of formatted variables. Each variable 1698 @return A tuple consisting of a list of formatted variables. Each
1663 entry is a tuple of three elements, the variable name, its type and 1699 variable entry is a tuple of three elements, the variable name,
1664 value. 1700 its type and value.
1665 """ 1701 """
1666 varlist = [] 1702 varlist = []
1667 if scope: 1703 if scope:
1668 patternFilterObjects = self.globalsFilterObjects 1704 patternFilterObjects = self.globalsFilterObjects
1669 else: 1705 else:
1701 try: 1737 try:
1702 if ConfigVarTypeStrings.index(valtype) in filter: 1738 if ConfigVarTypeStrings.index(valtype) in filter:
1703 continue 1739 continue
1704 except ValueError: 1740 except ValueError:
1705 if valtype == "classobj": 1741 if valtype == "classobj":
1706 if ConfigVarTypeStrings.index('instance') in filter: 1742 if ConfigVarTypeStrings.index(
1743 'instance') in filter:
1707 continue 1744 continue
1708 elif valtype == "sip.methoddescriptor": 1745 elif valtype == "sip.methoddescriptor":
1709 if ConfigVarTypeStrings.index('instance method') in filter: 1746 if ConfigVarTypeStrings.index(
1747 'instance method') in filter:
1710 continue 1748 continue
1711 elif valtype == "sip.enumtype": 1749 elif valtype == "sip.enumtype":
1712 if ConfigVarTypeStrings.index('class') in filter: 1750 if ConfigVarTypeStrings.index('class') in filter:
1713 continue 1751 continue
1714 elif not valtype.startswith("PySide") and \ 1752 elif not valtype.startswith("PySide") and \
1797 1835
1798 @param filename the program to be debugged (string) 1836 @param filename the program to be debugged (string)
1799 @param host hostname of the debug server (string) 1837 @param host hostname of the debug server (string)
1800 @param port portnumber of the debug server (int) 1838 @param port portnumber of the debug server (int)
1801 @param enableTrace flag to enable the tracing function (boolean) 1839 @param enableTrace flag to enable the tracing function (boolean)
1802 @param exceptions flag to enable exception reporting of the IDE (boolean) 1840 @param exceptions flag to enable exception reporting of the IDE
1803 @param tracePython flag to enable tracing into the Python library (boolean) 1841 (boolean)
1804 @param redirect flag indicating redirection of stdin, stdout and stderr (boolean) 1842 @param tracePython flag to enable tracing into the Python library
1843 (boolean)
1844 @param redirect flag indicating redirection of stdin, stdout and
1845 stderr (boolean)
1805 """ 1846 """
1806 global debugClient 1847 global debugClient
1807 if host is None: 1848 if host is None:
1808 host = os.getenv('ERICHOST', 'localhost') 1849 host = os.getenv('ERICHOST', 'localhost')
1809 if port is None: 1850 if port is None:
1819 except IndexError: 1860 except IndexError:
1820 self.running = None 1861 self.running = None
1821 if self.running: 1862 if self.running:
1822 self.__setCoding(self.running) 1863 self.__setCoding(self.running)
1823 self.passive = 1 1864 self.passive = 1
1824 self.write("%s%s|%d\n" % (DebugProtocol.PassiveStartup, self.running, exceptions)) 1865 self.write("%s%s|%d\n" % (
1866 DebugProtocol.PassiveStartup, self.running, exceptions))
1825 self.__interact() 1867 self.__interact()
1826 1868
1827 # setup the debugger variables 1869 # setup the debugger variables
1828 self._fncache = {} 1870 self._fncache = {}
1829 self.dircache = [] 1871 self.dircache = []
1850 @param progargs commandline for the program to be debugged 1892 @param progargs commandline for the program to be debugged
1851 (list of strings) 1893 (list of strings)
1852 @param wd working directory for the program execution (string) 1894 @param wd working directory for the program execution (string)
1853 @param host hostname of the debug server (string) 1895 @param host hostname of the debug server (string)
1854 @param port portnumber of the debug server (int) 1896 @param port portnumber of the debug server (int)
1855 @param exceptions flag to enable exception reporting of the IDE (boolean) 1897 @param exceptions flag to enable exception reporting of the IDE
1856 @param tracePython flag to enable tracing into the Python library (boolean) 1898 (boolean)
1857 @param redirect flag indicating redirection of stdin, stdout and stderr (boolean) 1899 @param tracePython flag to enable tracing into the Python library
1900 (boolean)
1901 @param redirect flag indicating redirection of stdin, stdout and
1902 stderr (boolean)
1858 """ 1903 """
1859 if host is None: 1904 if host is None:
1860 host = os.getenv('ERICHOST', 'localhost') 1905 host = os.getenv('ERICHOST', 'localhost')
1861 if port is None: 1906 if port is None:
1862 port = os.getenv('ERICPORT', 42424) 1907 port = os.getenv('ERICPORT', 42424)
1878 self.mainFrame = None 1923 self.mainFrame = None
1879 self.inRawMode = 0 1924 self.inRawMode = 0
1880 self.debugging = 1 1925 self.debugging = 1
1881 1926
1882 self.passive = 1 1927 self.passive = 1
1883 self.write("%s%s|%d\n" % (DebugProtocol.PassiveStartup, self.running, exceptions)) 1928 self.write("%s%s|%d\n" % (
1929 DebugProtocol.PassiveStartup, self.running, exceptions))
1884 self.__interact() 1930 self.__interact()
1885 1931
1886 self.attachThread(mainThread=1) 1932 self.attachThread(mainThread=1)
1887 self.mainThread.tracePython = tracePython 1933 self.mainThread.tracePython = tracePython
1888 1934
1891 sys.excepthook = self.__unhandled_exception 1937 sys.excepthook = self.__unhandled_exception
1892 1938
1893 # This will eventually enter a local event loop. 1939 # This will eventually enter a local event loop.
1894 # Note the use of backquotes to cause a repr of self.running. The 1940 # Note the use of backquotes to cause a repr of self.running. The
1895 # need for this is on Windows os where backslash is the path separator. 1941 # need for this is on Windows os where backslash is the path separator.
1896 # They will get inadvertantly stripped away during the eval causing IOErrors 1942 # They will get inadvertantly stripped away during the eval causing
1897 # if self.running is passed as a normal str. 1943 # IOErrors if self.running is passed as a normal str.
1898 self.debugMod.__dict__['__file__'] = self.running 1944 self.debugMod.__dict__['__file__'] = self.running
1899 sys.modules['__main__'] = self.debugMod 1945 sys.modules['__main__'] = self.debugMod
1900 res = self.mainThread.run('execfile(' + repr(self.running) + ')', 1946 res = self.mainThread.run('execfile(' + repr(self.running) + ')',
1901 self.debugMod.__dict__) 1947 self.debugMod.__dict__)
1902 self.progTerminated(res) 1948 self.progTerminated(res)
1928 version = 'v4' 1974 version = 'v4'
1929 if version == 'v4': 1975 if version == 'v4':
1930 family = socket.AF_INET 1976 family = socket.AF_INET
1931 else: 1977 else:
1932 family = socket.AF_INET6 1978 family = socket.AF_INET6
1933 return socket.getaddrinfo(host, None, family, socket.SOCK_STREAM)[0][4][0] 1979 return socket.getaddrinfo(host, None, family,
1980 socket.SOCK_STREAM)[0][4][0]
1934 1981
1935 def main(self): 1982 def main(self):
1936 """ 1983 """
1937 Public method implementing the main method. 1984 Public method implementing the main method.
1938 """ 1985 """
1986 print "No program given. Aborting!" 2033 print "No program given. Aborting!"
1987 else: 2034 else:
1988 if not self.noencoding: 2035 if not self.noencoding:
1989 self.__coding = self.defaultCoding 2036 self.__coding = self.defaultCoding
1990 self.startProgInDebugger(args, wd, host, port, 2037 self.startProgInDebugger(args, wd, host, port,
1991 exceptions=exceptions, tracePython=tracePython, 2038 exceptions=exceptions,
2039 tracePython=tracePython,
1992 redirect=redirect) 2040 redirect=redirect)
1993 else: 2041 else:
1994 if sys.argv[1] == '--no-encoding': 2042 if sys.argv[1] == '--no-encoding':
1995 self.noencoding = True 2043 self.noencoding = True
1996 del sys.argv[1] 2044 del sys.argv[1]
2050 self.sessionClose(0) 2098 self.sessionClose(0)
2051 return pid 2099 return pid
2052 2100
2053 def close(self, fd): 2101 def close(self, fd):
2054 """ 2102 """
2055 Private method implementing a close method as a replacement for os.close(). 2103 Private method implementing a close method as a replacement for
2104 os.close().
2056 2105
2057 It prevents the debugger connections from being closed. 2106 It prevents the debugger connections from being closed.
2058 2107
2059 @param fd file descriptor to be closed (integer) 2108 @param fd file descriptor to be closed (integer)
2060 """ 2109 """
2070 environment variable. 2119 environment variable.
2071 2120
2072 @param firstEntry entry to be put first in sys.path (string) 2121 @param firstEntry entry to be put first in sys.path (string)
2073 @return path list for use as sys.path (list of strings) 2122 @return path list for use as sys.path (list of strings)
2074 """ 2123 """
2075 sysPath = [path for path in os.environ.get("PYTHONPATH", "").split(os.pathsep) 2124 sysPath = [path for path in os.environ.get("PYTHONPATH", "")
2125 .split(os.pathsep)
2076 if path not in sys.path] + sys.path[:] 2126 if path not in sys.path] + sys.path[:]
2077 if "" in sysPath: 2127 if "" in sysPath:
2078 sysPath.remove("") 2128 sysPath.remove("")
2079 sysPath.insert(0, firstEntry) 2129 sysPath.insert(0, firstEntry)
2080 sysPath.insert(0, '') 2130 sysPath.insert(0, '')

eric ide

mercurial