blob: 92a588cbaa938d466113f7b56b905b146bb7196d [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001''' pydevd - a debugging daemon
2This is the daemon you launch for python remote debugging.
3
4Protocol:
5each command has a format:
6 id\tsequence-num\ttext
7 id: protocol command number
8 sequence-num: each request has a sequence number. Sequence numbers
9 originating at the debugger are odd, sequence numbers originating
10 at the daemon are even. Every response uses the same sequence number
11 as the request.
12 payload: it is protocol dependent. When response is a complex structure, it
13 is returned as XML. Each attribute value is urlencoded, and then the whole
14 payload is urlencoded again to prevent stray characters corrupting protocol/xml encodings
15
16 Commands:
17
18 NUMBER NAME FROM* ARGUMENTS RESPONSE NOTE
19100 series: program execution
20 101 RUN JAVA - -
21 102 LIST_THREADS JAVA RETURN with XML listing of all threads
22 103 THREAD_CREATE PYDB - XML with thread information
23 104 THREAD_KILL JAVA id (or * to exit) kills the thread
24 PYDB id nofies JAVA that thread was killed
25 105 THREAD_SUSPEND JAVA XML of the stack, suspends the thread
26 reason for suspension
27 PYDB id notifies JAVA that thread was suspended
28
29 106 CMD_THREAD_RUN JAVA id resume the thread
30 PYDB id \t reason notifies JAVA that thread was resumed
31
32 107 STEP_INTO JAVA thread_id
33 108 STEP_OVER JAVA thread_id
34 109 STEP_RETURN JAVA thread_id
35
36 110 GET_VARIABLE JAVA thread_id \t frame_id \t GET_VARIABLE with XML of var content
37 FRAME|GLOBAL \t attributes*
38
39 111 SET_BREAK JAVA file/line of the breakpoint
40 112 REMOVE_BREAK JAVA file/line of the return
41 113 CMD_EVALUATE_EXPRESSION JAVA expression result of evaluating the expression
42 114 CMD_GET_FRAME JAVA request for frame contents
43 115 CMD_EXEC_EXPRESSION JAVA
44 116 CMD_WRITE_TO_CONSOLE PYDB
45 117 CMD_CHANGE_VARIABLE
46 118 CMD_RUN_TO_LINE
47 119 CMD_RELOAD_CODE
48 120 CMD_GET_COMPLETIONS JAVA
49
50500 series diagnostics/ok
51 501 VERSION either Version string (1.0) Currently just used at startup
52 502 RETURN either Depends on caller -
53
54900 series: errors
55 901 ERROR either - This is reserved for unexpected errors.
56
57 * JAVA - remote debugger, the java end
58 * PYDB - pydevd, the python end
59'''
60from pydevd_constants import * #@UnusedWildImport
61
62import sys
63
Tor Norbyec3d3a902014-09-04 13:24:04 -070064from _pydev_imps import _pydev_time as time, _pydev_thread
65from _pydev_imps import _pydev_thread as thread
66import _pydev_threading as threading
Tor Norbye1aa2e092014-08-20 17:01:23 -070067from _pydev_imps._pydev_socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
68from pydev_imports import _queue
Tor Norbye3a2425a2013-11-04 10:16:08 -080069
70try:
Tor Norbyec667c1f2014-05-28 17:06:51 -070071 from urllib import quote, quote_plus, unquote, unquote_plus
Tor Norbye3a2425a2013-11-04 10:16:08 -080072except:
Tor Norbyec667c1f2014-05-28 17:06:51 -070073 from urllib.parse import quote, quote_plus, unquote, unquote_plus #@Reimport @UnresolvedImport
74import pydevconsole
Tor Norbye3a2425a2013-11-04 10:16:08 -080075import pydevd_vars
Tor Norbye3a2425a2013-11-04 10:16:08 -080076import pydevd_tracing
77import pydevd_vm_type
78import pydevd_file_utils
79import traceback
Tor Norbyec667c1f2014-05-28 17:06:51 -070080from pydevd_utils import quote_smart as quote, compare_object_attrs, cmp_to_key, to_string
Tor Norbye92584642014-04-17 08:39:25 -070081import pydev_log
Tor Norbyec667c1f2014-05-28 17:06:51 -070082import _pydev_completer
Tor Norbye3a2425a2013-11-04 10:16:08 -080083
84from pydevd_tracing import GetExceptionTracebackStr
Tor Norbye1aa2e092014-08-20 17:01:23 -070085import pydevd_console
86from pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules
Tor Norbyec667c1f2014-05-28 17:06:51 -070087
Tor Norbye3a2425a2013-11-04 10:16:08 -080088
Tor Norbye3a2425a2013-11-04 10:16:08 -080089
90CMD_RUN = 101
91CMD_LIST_THREADS = 102
92CMD_THREAD_CREATE = 103
93CMD_THREAD_KILL = 104
94CMD_THREAD_SUSPEND = 105
95CMD_THREAD_RUN = 106
96CMD_STEP_INTO = 107
97CMD_STEP_OVER = 108
98CMD_STEP_RETURN = 109
99CMD_GET_VARIABLE = 110
100CMD_SET_BREAK = 111
101CMD_REMOVE_BREAK = 112
102CMD_EVALUATE_EXPRESSION = 113
103CMD_GET_FRAME = 114
104CMD_EXEC_EXPRESSION = 115
105CMD_WRITE_TO_CONSOLE = 116
106CMD_CHANGE_VARIABLE = 117
107CMD_RUN_TO_LINE = 118
108CMD_RELOAD_CODE = 119
109CMD_GET_COMPLETIONS = 120
Tor Norbye1aa2e092014-08-20 17:01:23 -0700110
111# Note: renumbered (conflicted on merge)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800112CMD_CONSOLE_EXEC = 121
113CMD_ADD_EXCEPTION_BREAK = 122
114CMD_REMOVE_EXCEPTION_BREAK = 123
115CMD_LOAD_SOURCE = 124
116CMD_ADD_DJANGO_EXCEPTION_BREAK = 125
117CMD_REMOVE_DJANGO_EXCEPTION_BREAK = 126
118CMD_SET_NEXT_STATEMENT = 127
119CMD_SMART_STEP_INTO = 128
120CMD_EXIT = 129
121CMD_SIGNATURE_CALL_TRACE = 130
Tor Norbye1aa2e092014-08-20 17:01:23 -0700122
123
124
125CMD_SET_PY_EXCEPTION = 131
126CMD_GET_FILE_CONTENTS = 132
127CMD_SET_PROPERTY_TRACE = 133
128# Pydev debug console commands
129CMD_EVALUATE_CONSOLE_EXPRESSION = 134
130CMD_RUN_CUSTOM_OPERATION = 135
131CMD_GET_BREAKPOINT_EXCEPTION = 136
132CMD_STEP_CAUGHT_EXCEPTION = 137
133CMD_SEND_CURR_EXCEPTION_TRACE = 138
134CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED = 139
135CMD_IGNORE_THROWN_EXCEPTION_AT = 140
136CMD_ENABLE_DONT_TRACE = 141
Tor Norbyec3d3a902014-09-04 13:24:04 -0700137CMD_SHOW_CONSOLE = 142
Tor Norbye1aa2e092014-08-20 17:01:23 -0700138
139
140
Tor Norbye3a2425a2013-11-04 10:16:08 -0800141CMD_VERSION = 501
142CMD_RETURN = 502
143CMD_ERROR = 901
144
145ID_TO_MEANING = {
146 '101':'CMD_RUN',
147 '102':'CMD_LIST_THREADS',
148 '103':'CMD_THREAD_CREATE',
149 '104':'CMD_THREAD_KILL',
150 '105':'CMD_THREAD_SUSPEND',
151 '106':'CMD_THREAD_RUN',
152 '107':'CMD_STEP_INTO',
153 '108':'CMD_STEP_OVER',
154 '109':'CMD_STEP_RETURN',
155 '110':'CMD_GET_VARIABLE',
156 '111':'CMD_SET_BREAK',
157 '112':'CMD_REMOVE_BREAK',
158 '113':'CMD_EVALUATE_EXPRESSION',
159 '114':'CMD_GET_FRAME',
160 '115':'CMD_EXEC_EXPRESSION',
161 '116':'CMD_WRITE_TO_CONSOLE',
162 '117':'CMD_CHANGE_VARIABLE',
163 '118':'CMD_RUN_TO_LINE',
164 '119':'CMD_RELOAD_CODE',
165 '120':'CMD_GET_COMPLETIONS',
166 '121':'CMD_CONSOLE_EXEC',
167 '122':'CMD_ADD_EXCEPTION_BREAK',
168 '123':'CMD_REMOVE_EXCEPTION_BREAK',
169 '124':'CMD_LOAD_SOURCE',
170 '125':'CMD_ADD_DJANGO_EXCEPTION_BREAK',
171 '126':'CMD_REMOVE_DJANGO_EXCEPTION_BREAK',
172 '127':'CMD_SET_NEXT_STATEMENT',
173 '128':'CMD_SMART_STEP_INTO',
174 '129': 'CMD_EXIT',
175 '130': 'CMD_SIGNATURE_CALL_TRACE',
Tor Norbye1aa2e092014-08-20 17:01:23 -0700176
177 '131': 'CMD_SET_PY_EXCEPTION',
178 '132': 'CMD_GET_FILE_CONTENTS',
179 '133': 'CMD_SET_PROPERTY_TRACE',
180 '134': 'CMD_EVALUATE_CONSOLE_EXPRESSION',
181 '135': 'CMD_RUN_CUSTOM_OPERATION',
182 '136': 'CMD_GET_BREAKPOINT_EXCEPTION',
183 '137': 'CMD_STEP_CAUGHT_EXCEPTION',
184 '138': 'CMD_SEND_CURR_EXCEPTION_TRACE',
185 '139': 'CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED',
186 '140': 'CMD_IGNORE_THROWN_EXCEPTION_AT',
187 '141': 'CMD_ENABLE_DONT_TRACE',
188
Tor Norbye3a2425a2013-11-04 10:16:08 -0800189 '501':'CMD_VERSION',
190 '502':'CMD_RETURN',
191 '901':'CMD_ERROR',
192 }
193
194MAX_IO_MSG_SIZE = 1000 #if the io is too big, we'll not send all (could make the debugger too non-responsive)
195#this number can be changed if there's need to do so
196
197VERSION_STRING = "@@BUILD_NUMBER@@"
198
Tor Norbyec667c1f2014-05-28 17:06:51 -0700199from _pydev_filesystem_encoding import getfilesystemencoding
200file_system_encoding = getfilesystemencoding()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800201
202#--------------------------------------------------------------------------------------------------- UTILITIES
203
204#=======================================================================================================================
205# PydevdLog
206#=======================================================================================================================
207def PydevdLog(level, *args):
208 """ levels are:
209 0 most serious warnings/errors
210 1 warnings/significant events
211 2 informational trace
212 """
213 if level <= DebugInfoHolder.DEBUG_TRACE_LEVEL:
214 #yes, we can have errors printing if the console of the program has been finished (and we're still trying to print something)
215 try:
216 sys.stderr.write('%s\n' % (args,))
217 except:
218 pass
219
220#=======================================================================================================================
221# GlobalDebuggerHolder
222#=======================================================================================================================
223class GlobalDebuggerHolder:
224 '''
225 Holder for the global debugger.
226 '''
227 globalDbg = None
228
229#=======================================================================================================================
230# GetGlobalDebugger
231#=======================================================================================================================
232def GetGlobalDebugger():
233 return GlobalDebuggerHolder.globalDbg
234
235#=======================================================================================================================
236# SetGlobalDebugger
237#=======================================================================================================================
238def SetGlobalDebugger(dbg):
239 GlobalDebuggerHolder.globalDbg = dbg
240
241
242#------------------------------------------------------------------- ACTUAL COMM
243
244#=======================================================================================================================
245# PyDBDaemonThread
246#=======================================================================================================================
Tor Norbyec3d3a902014-09-04 13:24:04 -0700247class PyDBDaemonThread:
248
249 created_pydb_daemon_threads = {}
Tor Norbye3a2425a2013-11-04 10:16:08 -0800250
251 def __init__(self):
Tor Norbyec3d3a902014-09-04 13:24:04 -0700252 # Note: subclasses are always daemon threads.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800253 self.killReceived = False
254 self.dontTraceMe = True
255
Tor Norbyec3d3a902014-09-04 13:24:04 -0700256 def setName(self, name):
257 self.name = name
Tor Norbye3a2425a2013-11-04 10:16:08 -0800258
Tor Norbyec3d3a902014-09-04 13:24:04 -0700259 def start(self):
260 import pydev_monkey
261 start_new_thread = pydev_monkey.get_original_start_new_thread(_pydev_thread)
262 start_new_thread(self.run, ())
263
264 def run(self):
265 created_pydb_daemon = self.created_pydb_daemon_threads
266 created_pydb_daemon[self] = 1
267 dummy_thread = threading.currentThread()
268 dummy_thread.is_pydev_daemon_thread = True
269 try:
270 try:
271 if IS_JYTHON:
272 import org.python.core as PyCore #@UnresolvedImport
273 ss = PyCore.PySystemState()
274 # Note: Py.setSystemState() affects only the current thread.
275 PyCore.Py.setSystemState(ss)
276
277 self.OnRun()
278 except:
279 if sys is not None and traceback is not None:
280 traceback.print_exc()
281 finally:
282 del created_pydb_daemon[self]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800283
284 def OnRun(self):
285 raise NotImplementedError('Should be reimplemented by: %s' % self.__class__)
286
287 def doKillPydevThread(self):
288 #that was not working very well because jython gave some socket errors
289 self.killReceived = True
290
Tor Norbye3a2425a2013-11-04 10:16:08 -0800291 def stopTrace(self):
292 if self.dontTraceMe:
Tor Norbyec3d3a902014-09-04 13:24:04 -0700293
294 disable_tracing = True
295
296 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.hexversion <= 0x020201f0:
297 # don't run untraced threads if we're in jython 2.2.1 or lower
298 # jython bug: if we start a thread and another thread changes the tracing facility
299 # it affects other threads (it's not set only for the thread but globally)
300 # Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1870039&group_id=12867&atid=112867
301 disable_tracing = False
302
303 if disable_tracing:
304 pydevd_tracing.SetTrace(None) # no debugging on this thread
Tor Norbye3a2425a2013-11-04 10:16:08 -0800305
306
307#=======================================================================================================================
308# ReaderThread
309#=======================================================================================================================
310class ReaderThread(PyDBDaemonThread):
311 """ reader thread reads and dispatches commands in an infinite loop """
312
313 def __init__(self, sock):
314 PyDBDaemonThread.__init__(self)
315 self.sock = sock
316 self.setName("pydevd.Reader")
317
318
319 def doKillPydevThread(self):
320 #We must close the socket so that it doesn't stay halted there.
321 self.killReceived = True
322 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700323 self.sock.shutdown(SHUT_RD) #shutdown the socket for read
Tor Norbye3a2425a2013-11-04 10:16:08 -0800324 except:
325 #just ignore that
326 pass
327
328 def OnRun(self):
329 self.stopTrace()
330 buffer = ""
331 try:
332
333 while not self.killReceived:
334 try:
335 r = self.sock.recv(1024)
336 except:
337 if not self.killReceived:
338 self.handleExcept()
339 return #Finished communication.
Tor Norbyec667c1f2014-05-28 17:06:51 -0700340
341 #Note: the java backend is always expected to pass utf-8 encoded strings. We now work with unicode
342 #internally and thus, we may need to convert to the actual encoding where needed (i.e.: filenames
343 #on python 2 may need to be converted to the filesystem encoding).
344 if hasattr(r, 'decode'):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800345 r = r.decode('utf-8')
346
347 buffer += r
348 if DebugInfoHolder.DEBUG_RECORD_SOCKET_READS:
349 pydev_log.debug('received >>%s<<\n' % (buffer,))
350
351 if len(buffer) == 0:
352 self.handleExcept()
353 break
354 while buffer.find('\n') != -1:
355 command, buffer = buffer.split('\n', 1)
Tor Norbye1fff8e22014-03-10 13:13:45 -0700356
Tor Norbye3a2425a2013-11-04 10:16:08 -0800357 args = command.split('\t', 2)
358 try:
Tor Norbye1fff8e22014-03-10 13:13:45 -0700359 cmd_id = int(args[0])
360 pydev_log.debug('Received command: %s %s\n' % (ID_TO_MEANING.get(str(cmd_id), '???'), command,))
361 self.processCommand(cmd_id, int(args[1]), args[2])
Tor Norbye3a2425a2013-11-04 10:16:08 -0800362 except:
363 traceback.print_exc()
364 sys.stderr.write("Can't process net command: %s\n" % command)
365 sys.stderr.flush()
366
367 except:
368 traceback.print_exc()
369 self.handleExcept()
370
371
372 def handleExcept(self):
373 GlobalDebuggerHolder.globalDbg.FinishDebuggingSession()
374
375 def processCommand(self, cmd_id, seq, text):
376 GlobalDebuggerHolder.globalDbg.processNetCommand(cmd_id, seq, text)
377
378
379#----------------------------------------------------------------------------------- SOCKET UTILITIES - WRITER
380#=======================================================================================================================
381# WriterThread
382#=======================================================================================================================
383class WriterThread(PyDBDaemonThread):
384 """ writer thread writes out the commands in an infinite loop """
385 def __init__(self, sock):
386 PyDBDaemonThread.__init__(self)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800387 self.sock = sock
388 self.setName("pydevd.Writer")
389 self.cmdQueue = _queue.Queue()
390 if pydevd_vm_type.GetVmType() == 'python':
391 self.timeout = 0
392 else:
393 self.timeout = 0.1
394
395 def addCommand(self, cmd):
396 """ cmd is NetCommand """
397 if not self.killReceived: #we don't take new data after everybody die
398 self.cmdQueue.put(cmd)
399
400 def OnRun(self):
401 """ just loop and write responses """
402
403 self.stopTrace()
Tor Norbyec3d3a902014-09-04 13:24:04 -0700404 get_has_timeout = sys.hexversion >= 0x02030000 # 2.3 onwards have it.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800405 try:
406 while True:
407 try:
408 try:
Tor Norbyec3d3a902014-09-04 13:24:04 -0700409 if get_has_timeout:
410 cmd = self.cmdQueue.get(1, 0.1)
411 else:
412 time.sleep(.01)
413 cmd = self.cmdQueue.get(0)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800414 except _queue.Empty:
415 if self.killReceived:
416 try:
417 self.sock.shutdown(SHUT_WR)
418 self.sock.close()
419 except:
420 pass
Tor Norbye3a2425a2013-11-04 10:16:08 -0800421
422 return #break if queue is empty and killReceived
423 else:
424 continue
425 except:
426 #PydevdLog(0, 'Finishing debug communication...(1)')
427 #when liberating the thread here, we could have errors because we were shutting down
428 #but the thread was still not liberated
429 return
430 out = cmd.getOutgoing()
431
432 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700433 out_message = 'sending cmd --> '
434 out_message += "%20s" % ID_TO_MEANING.get(out[:3], 'UNKNOWN')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800435 out_message += ' '
Tor Norbyec667c1f2014-05-28 17:06:51 -0700436 out_message += unquote(unquote(out)).replace('\n', ' ')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800437 try:
438 sys.stderr.write('%s\n' % (out_message,))
439 except:
440 pass
441
442 if IS_PY3K:
443 out = bytearray(out, 'utf-8')
444 self.sock.send(out) #TODO: this does not guarantee that all message are sent (and jython does not have a send all)
445 if cmd.id == CMD_EXIT:
446 break
447 if time is None:
448 break #interpreter shutdown
449 time.sleep(self.timeout)
450 except Exception:
451 GlobalDebuggerHolder.globalDbg.FinishDebuggingSession()
452 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 0:
453 traceback.print_exc()
454
455
456
457
458#--------------------------------------------------- CREATING THE SOCKET THREADS
459
460#=======================================================================================================================
461# StartServer
462#=======================================================================================================================
463def StartServer(port):
464 """ binds to a port, waits for the debugger to connect """
465 s = socket(AF_INET, SOCK_STREAM)
466 s.bind(('', port))
467 s.listen(1)
468 newSock, _addr = s.accept()
469 return newSock
470
471#=======================================================================================================================
472# StartClient
473#=======================================================================================================================
474def StartClient(host, port):
475 """ connects to a host/port """
476 PydevdLog(1, "Connecting to ", host, ":", str(port))
477
478 s = socket(AF_INET, SOCK_STREAM)
479
Tor Norbye2e5965e2014-07-25 12:24:15 -0700480 MAX_TRIES = 100
Tor Norbye3a2425a2013-11-04 10:16:08 -0800481 i = 0
482 while i<MAX_TRIES:
483 try:
484 s.connect((host, port))
485 except:
486 i+=1
487 time.sleep(0.2)
488 continue
489 PydevdLog(1, "Connected.")
490 return s
491
492 sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
493 sys.stderr.flush()
494 traceback.print_exc()
495 sys.exit(1) #TODO: is it safe?
496
497
498
499#------------------------------------------------------------------------------------ MANY COMMUNICATION STUFF
500
501#=======================================================================================================================
502# NetCommand
503#=======================================================================================================================
504class NetCommand:
505 """ Commands received/sent over the network.
506
507 Command can represent command received from the debugger,
508 or one to be sent by daemon.
509 """
510 next_seq = 0 # sequence numbers
511
512 def __init__(self, id, seq, text):
513 """ smart handling of paramaters
514 if sequence is 0, new sequence will be generated
515 if text has carriage returns they'll be replaced"""
516 self.id = id
517 if (seq == 0): seq = self.getNextSeq()
518 self.seq = seq
519 self.text = text
520 self.outgoing = self.makeMessage(id, seq, text)
521
522 def getNextSeq(self):
523 """ returns next sequence number """
524 NetCommand.next_seq += 2
525 return NetCommand.next_seq
526
527 def getOutgoing(self):
528 """ returns the outgoing message"""
529 return self.outgoing
530
531 def makeMessage(self, cmd, seq, payload):
532 encoded = quote(to_string(payload), '/<>_=" \t')
533 return str(cmd) + '\t' + str(seq) + '\t' + encoded + "\n"
534
535#=======================================================================================================================
536# NetCommandFactory
537#=======================================================================================================================
538class NetCommandFactory:
539
540 def __init_(self):
541 self.next_seq = 0
542
543 def threadToXML(self, thread):
544 """ thread information as XML """
545 name = pydevd_vars.makeValidXmlValue(thread.getName())
546 cmdText = '<thread name="%s" id="%s" />' % (quote(name), GetThreadId(thread))
547 return cmdText
548
549 def makeErrorMessage(self, seq, text):
550 cmd = NetCommand(CMD_ERROR, seq, text)
551 if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2:
552 sys.stderr.write("Error: %s" % (text,))
553 return cmd
554
555 def makeThreadCreatedMessage(self, thread):
556 cmdText = "<xml>" + self.threadToXML(thread) + "</xml>"
557 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
558
Tor Norbyec667c1f2014-05-28 17:06:51 -0700559
560 def makeCustomFrameCreatedMessage(self, frameId, frameDescription):
561 frameDescription = pydevd_vars.makeValidXmlValue(frameDescription)
562 cmdText = '<xml><thread name="%s" id="%s"/></xml>' % (frameDescription, frameId)
563 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
564
565
Tor Norbye3a2425a2013-11-04 10:16:08 -0800566 def makeListThreadsMessage(self, seq):
567 """ returns thread listing as XML """
568 try:
569 t = threading.enumerate()
570 cmdText = "<xml>"
571 for i in t:
572 if t.isAlive():
573 cmdText += self.threadToXML(i)
574 cmdText += "</xml>"
575 return NetCommand(CMD_RETURN, seq, cmdText)
576 except:
577 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
578
579 def makeVariableChangedMessage(self, seq, payload):
580 # notify debugger that value was changed successfully
581 return NetCommand(CMD_RETURN, seq, payload)
582
583 def makeIoMessage(self, v, ctx, dbg=None):
584 '''
585 @param v: the message to pass to the debug server
586 @param ctx: 1 for stdio 2 for stderr
587 @param dbg: If not none, add to the writer
588 '''
589
590 try:
591 if len(v) > MAX_IO_MSG_SIZE:
592 v = v[0:MAX_IO_MSG_SIZE]
593 v += '...'
594
595 v = pydevd_vars.makeValidXmlValue(quote(v, '/>_= \t'))
596 net = NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '<xml><io s="%s" ctx="%s"/></xml>' % (v, ctx))
597 except:
598 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
599
600 if dbg:
601 dbg.writer.addCommand(net)
602
603 return net
604
605 def makeVersionMessage(self, seq):
606 try:
607 return NetCommand(CMD_VERSION, seq, VERSION_STRING)
608 except:
609 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
610
611 def makeThreadKilledMessage(self, id):
612 try:
613 return NetCommand(CMD_THREAD_KILL, 0, str(id))
614 except:
615 return self.makeErrorMessage(0, GetExceptionTracebackStr())
616
Tor Norbye1aa2e092014-08-20 17:01:23 -0700617 def makeThreadSuspendStr(self, thread_id, frame, stop_reason, message):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800618 """ <xml>
619 <thread id="id" stop_reason="reason">
620 <frame id="id" name="functionName " file="file" line="line">
621 <var variable stuffff....
622 </frame>
623 </thread>
Tor Norbye1aa2e092014-08-20 17:01:23 -0700624 """
625 cmdTextList = ["<xml>"]
626
627 if message:
628 message = pydevd_vars.makeValidXmlValue(str(message))
629
630 cmdTextList.append('<thread id="%s" stop_reason="%s" message="%s">' % (thread_id, stop_reason, message))
631
632 curFrame = frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800633 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700634 while curFrame:
635 #print cmdText
636 myId = str(id(curFrame))
637 #print "id is ", myId
Tor Norbye3a2425a2013-11-04 10:16:08 -0800638
Tor Norbye1aa2e092014-08-20 17:01:23 -0700639 if curFrame.f_code is None:
640 break #Iron Python sometimes does not have it!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800641
Tor Norbye1aa2e092014-08-20 17:01:23 -0700642 myName = curFrame.f_code.co_name #method name (if in method) or ? if global
643 if myName is None:
644 break #Iron Python sometimes does not have it!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800645
Tor Norbye1aa2e092014-08-20 17:01:23 -0700646 #print "name is ", myName
Tor Norbye3a2425a2013-11-04 10:16:08 -0800647
Tor Norbye1aa2e092014-08-20 17:01:23 -0700648 filename, base = pydevd_file_utils.GetFilenameAndBase(curFrame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800649
Tor Norbye1aa2e092014-08-20 17:01:23 -0700650 myFile = pydevd_file_utils.NormFileToClient(filename)
651 if file_system_encoding.lower() != "utf-8" and hasattr(myFile, "decode"):
652 # myFile is a byte string encoded using the file system encoding
653 # convert it to utf8
654 myFile = myFile.decode(file_system_encoding).encode("utf-8")
Tor Norbye3a2425a2013-11-04 10:16:08 -0800655
Tor Norbye1aa2e092014-08-20 17:01:23 -0700656 #print "file is ", myFile
657 #myFile = inspect.getsourcefile(curFrame) or inspect.getfile(frame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800658
Tor Norbye1aa2e092014-08-20 17:01:23 -0700659 myLine = str(curFrame.f_lineno)
660 #print "line is ", myLine
Tor Norbye3a2425a2013-11-04 10:16:08 -0800661
Tor Norbye1aa2e092014-08-20 17:01:23 -0700662 #the variables are all gotten 'on-demand'
663 #variables = pydevd_vars.frameVarsToXML(curFrame.f_locals)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800664
Tor Norbye1aa2e092014-08-20 17:01:23 -0700665 variables = ''
666 cmdTextList.append('<frame id="%s" name="%s" ' % (myId , pydevd_vars.makeValidXmlValue(myName)))
667 cmdTextList.append('file="%s" line="%s">"' % (quote(myFile, '/>_= \t'), myLine))
668 cmdTextList.append(variables)
669 cmdTextList.append("</frame>")
670 curFrame = curFrame.f_back
671 except :
672 traceback.print_exc()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800673
Tor Norbye1aa2e092014-08-20 17:01:23 -0700674 cmdTextList.append("</thread></xml>")
675 return ''.join(cmdTextList)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800676
Tor Norbye1aa2e092014-08-20 17:01:23 -0700677 def makeThreadSuspendMessage(self, thread_id, frame, stop_reason, message):
678 try:
679 return NetCommand(CMD_THREAD_SUSPEND, 0, self.makeThreadSuspendStr(thread_id, frame, stop_reason, message))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800680 except:
681 return self.makeErrorMessage(0, GetExceptionTracebackStr())
682
683 def makeThreadRunMessage(self, id, reason):
684 try:
685 return NetCommand(CMD_THREAD_RUN, 0, str(id) + "\t" + str(reason))
686 except:
687 return self.makeErrorMessage(0, GetExceptionTracebackStr())
688
689 def makeGetVariableMessage(self, seq, payload):
690 try:
691 return NetCommand(CMD_GET_VARIABLE, seq, payload)
692 except Exception:
693 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
694
695 def makeGetFrameMessage(self, seq, payload):
696 try:
697 return NetCommand(CMD_GET_FRAME, seq, payload)
698 except Exception:
699 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
700
701
702 def makeEvaluateExpressionMessage(self, seq, payload):
703 try:
704 return NetCommand(CMD_EVALUATE_EXPRESSION, seq, payload)
705 except Exception:
706 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
707
708 def makeGetCompletionsMessage(self, seq, payload):
709 try:
710 return NetCommand(CMD_GET_COMPLETIONS, seq, payload)
711 except Exception:
712 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
713
Tor Norbye1aa2e092014-08-20 17:01:23 -0700714 def makeGetFileContents(self, seq, payload):
715 try:
716 return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload)
717 except Exception:
718 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
719
720 def makeSendBreakpointExceptionMessage(self, seq, payload):
721 try:
722 return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload)
723 except Exception:
724 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
725
726 def makeSendCurrExceptionTraceMessage(self, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj):
727 try:
728 while trace_obj.tb_next is not None:
729 trace_obj = trace_obj.tb_next
730
731 exc_type = pydevd_vars.makeValidXmlValue(str(exc_type)).replace('\t', ' ') or 'exception: type unknown'
732 exc_desc = pydevd_vars.makeValidXmlValue(str(exc_desc)).replace('\t', ' ') or 'exception: no description'
733
734 payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + \
735 self.makeThreadSuspendStr(thread_id, trace_obj.tb_frame, CMD_SEND_CURR_EXCEPTION_TRACE, '')
736
737 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload)
738 except Exception:
739 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
740
741 def makeSendCurrExceptionTraceProceededMessage(self, seq, thread_id):
742 try:
743 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id))
744 except:
745 return self.makeErrorMessage(0, GetExceptionTracebackStr())
746
747 def makeSendConsoleMessage(self, seq, payload):
748 try:
749 return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload)
750 except Exception:
751 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
752
753 def makeCustomOperationMessage(self, seq, payload):
754 try:
755 return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload)
756 except Exception:
757 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
758
Tor Norbye3a2425a2013-11-04 10:16:08 -0800759 def makeLoadSourceMessage(self, seq, source, dbg=None):
760 try:
761 net = NetCommand(CMD_LOAD_SOURCE, seq, '%s' % source)
762
763 except:
764 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
765
766 if dbg:
767 dbg.writer.addCommand(net)
768 return net
769
Tor Norbyec3d3a902014-09-04 13:24:04 -0700770 def makeShowConsoleMessage(self, thread_id, frame):
771 try:
772 return NetCommand(CMD_SHOW_CONSOLE, 0, self.makeThreadSuspendStr(thread_id, frame, CMD_SHOW_CONSOLE, ''))
773 except:
774 return self.makeErrorMessage(0, GetExceptionTracebackStr())
775
Tor Norbye3a2425a2013-11-04 10:16:08 -0800776 def makeExitMessage(self):
777 try:
778 net = NetCommand(CMD_EXIT, 0, '')
779
780 except:
781 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
782
783 return net
784
785INTERNAL_TERMINATE_THREAD = 1
786INTERNAL_SUSPEND_THREAD = 2
787
788
789#=======================================================================================================================
790# InternalThreadCommand
791#=======================================================================================================================
792class InternalThreadCommand:
793 """ internal commands are generated/executed by the debugger.
794
795 The reason for their existence is that some commands have to be executed
796 on specific threads. These are the InternalThreadCommands that get
797 get posted to PyDB.cmdQueue.
798 """
799
800 def canBeExecutedBy(self, thread_id):
801 '''By default, it must be in the same thread to be executed
802 '''
Tor Norbye1aa2e092014-08-20 17:01:23 -0700803 return self.thread_id == thread_id or self.thread_id.endswith('|' + thread_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800804
805 def doIt(self, dbg):
806 raise NotImplementedError("you have to override doIt")
807
Tor Norbyec667c1f2014-05-28 17:06:51 -0700808
809class ReloadCodeCommand(InternalThreadCommand):
810
811
812 def __init__(self, module_name, thread_id):
813 self.thread_id = thread_id
814 self.module_name = module_name
815 self.executed = False
Tor Norbyec3d3a902014-09-04 13:24:04 -0700816 self.lock = _pydev_thread.allocate_lock()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700817
818
819 def canBeExecutedBy(self, thread_id):
820 if self.thread_id == '*':
821 return True #Any thread can execute it!
822
823 return InternalThreadCommand.canBeExecutedBy(self, thread_id)
824
825
826 def doIt(self, dbg):
827 self.lock.acquire()
828 try:
829 if self.executed:
830 return
831 self.executed = True
832 finally:
833 self.lock.release()
834
835 module_name = self.module_name
836 if not DictContains(sys.modules, module_name):
837 if '.' in module_name:
838 new_module_name = module_name.split('.')[-1]
839 if DictContains(sys.modules, new_module_name):
840 module_name = new_module_name
841
842 if not DictContains(sys.modules, module_name):
843 sys.stderr.write('pydev debugger: Unable to find module to reload: "' + module_name + '".\n')
844 # Too much info...
845 # sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n')
846
847 else:
848 sys.stderr.write('pydev debugger: Start reloading module: "' + module_name + '" ... \n')
849 import pydevd_reload
850 if pydevd_reload.xreload(sys.modules[module_name]):
851 sys.stderr.write('pydev debugger: reload finished\n')
852 else:
853 sys.stderr.write('pydev debugger: reload finished without applying any change\n')
854
855
Tor Norbye3a2425a2013-11-04 10:16:08 -0800856#=======================================================================================================================
857# InternalTerminateThread
858#=======================================================================================================================
859class InternalTerminateThread(InternalThreadCommand):
860 def __init__(self, thread_id):
861 self.thread_id = thread_id
862
863 def doIt(self, dbg):
864 PydevdLog(1, "killing ", str(self.thread_id))
865 cmd = dbg.cmdFactory.makeThreadKilledMessage(self.thread_id)
866 dbg.writer.addCommand(cmd)
867
868
869#=======================================================================================================================
870# InternalRunThread
871#=======================================================================================================================
872class InternalRunThread(InternalThreadCommand):
873 def __init__(self, thread_id):
874 self.thread_id = thread_id
875
876 def doIt(self, dbg):
877 t = PydevdFindThreadById(self.thread_id)
878 if t:
879 t.additionalInfo.pydev_step_cmd = None
880 t.additionalInfo.pydev_step_stop = None
881 t.additionalInfo.pydev_state = STATE_RUN
882
883
884#=======================================================================================================================
885# InternalStepThread
886#=======================================================================================================================
887class InternalStepThread(InternalThreadCommand):
888 def __init__(self, thread_id, cmd_id):
889 self.thread_id = thread_id
890 self.cmd_id = cmd_id
891
892 def doIt(self, dbg):
893 t = PydevdFindThreadById(self.thread_id)
894 if t:
895 t.additionalInfo.pydev_step_cmd = self.cmd_id
896 t.additionalInfo.pydev_state = STATE_RUN
897
898#=======================================================================================================================
899# InternalSetNextStatementThread
900#=======================================================================================================================
901class InternalSetNextStatementThread(InternalThreadCommand):
902 def __init__(self, thread_id, cmd_id, line, func_name):
903 self.thread_id = thread_id
904 self.cmd_id = cmd_id
905 self.line = line
906 self.func_name = func_name
907
908 def doIt(self, dbg):
909 t = PydevdFindThreadById(self.thread_id)
910 if t:
911 t.additionalInfo.pydev_step_cmd = self.cmd_id
912 t.additionalInfo.pydev_next_line = int(self.line)
913 t.additionalInfo.pydev_func_name = self.func_name
914 t.additionalInfo.pydev_state = STATE_RUN
915
916
917#=======================================================================================================================
918# InternalGetVariable
919#=======================================================================================================================
920class InternalGetVariable(InternalThreadCommand):
921 """ gets the value of a variable """
922 def __init__(self, seq, thread_id, frame_id, scope, attrs):
923 self.sequence = seq
924 self.thread_id = thread_id
925 self.frame_id = frame_id
926 self.scope = scope
927 self.attributes = attrs
928
929 def doIt(self, dbg):
930 """ Converts request into python variable """
931 try:
932 xml = "<xml>"
933 valDict = pydevd_vars.resolveCompoundVariable(self.thread_id, self.frame_id, self.scope, self.attributes)
934 if valDict is None:
935 valDict = {}
936
937 keys = valDict.keys()
938 if hasattr(keys, 'sort'):
939 keys.sort(compare_object_attrs) #Python 3.0 does not have it
940 else:
941 if IS_PY3K:
942 keys = sorted(keys, key=cmp_to_key(compare_object_attrs)) #Jython 2.1 does not have it (and all must be compared as strings).
943 else:
944 keys = sorted(keys, cmp=compare_object_attrs) #Jython 2.1 does not have it (and all must be compared as strings).
945
946 for k in keys:
947 xml += pydevd_vars.varToXML(valDict[k], to_string(k))
948
949 xml += "</xml>"
950 cmd = dbg.cmdFactory.makeGetVariableMessage(self.sequence, xml)
951 dbg.writer.addCommand(cmd)
952 except Exception:
953 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error resolving variables " + GetExceptionTracebackStr())
954 dbg.writer.addCommand(cmd)
955
956
957#=======================================================================================================================
958# InternalChangeVariable
959#=======================================================================================================================
960class InternalChangeVariable(InternalThreadCommand):
961 """ changes the value of a variable """
962 def __init__(self, seq, thread_id, frame_id, scope, attr, expression):
963 self.sequence = seq
964 self.thread_id = thread_id
965 self.frame_id = frame_id
966 self.scope = scope
967 self.attr = attr
968 self.expression = expression
969
970 def doIt(self, dbg):
971 """ Converts request into python variable """
972 try:
973 result = pydevd_vars.changeAttrExpression(self.thread_id, self.frame_id, self.attr, self.expression)
974 xml = "<xml>"
975 xml += pydevd_vars.varToXML(result, "")
976 xml += "</xml>"
977 cmd = dbg.cmdFactory.makeVariableChangedMessage(self.sequence, xml)
978 dbg.writer.addCommand(cmd)
979 except Exception:
980 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error changing variable attr:%s expression:%s traceback:%s" % (self.attr, self.expression, GetExceptionTracebackStr()))
981 dbg.writer.addCommand(cmd)
982
983
984#=======================================================================================================================
985# InternalGetFrame
986#=======================================================================================================================
987class InternalGetFrame(InternalThreadCommand):
988 """ gets the value of a variable """
989 def __init__(self, seq, thread_id, frame_id):
990 self.sequence = seq
991 self.thread_id = thread_id
992 self.frame_id = frame_id
993
994 def doIt(self, dbg):
995 """ Converts request into python variable """
996 try:
997 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
998 if frame is not None:
999 xml = "<xml>"
1000 xml += pydevd_vars.frameVarsToXML(frame.f_locals)
1001 del frame
1002 xml += "</xml>"
1003 cmd = dbg.cmdFactory.makeGetFrameMessage(self.sequence, xml)
1004 dbg.writer.addCommand(cmd)
1005 else:
1006 #pydevd_vars.dumpFrames(self.thread_id)
1007 #don't print this error: frame not found: means that the client is not synchronized (but that's ok)
1008 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1009 dbg.writer.addCommand(cmd)
1010 except:
1011 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error resolving frame: %s from thread: %s" % (self.frame_id, self.thread_id))
1012 dbg.writer.addCommand(cmd)
1013
1014
1015#=======================================================================================================================
1016# InternalEvaluateExpression
1017#=======================================================================================================================
1018class InternalEvaluateExpression(InternalThreadCommand):
1019 """ gets the value of a variable """
1020
1021 def __init__(self, seq, thread_id, frame_id, expression, doExec, doTrim):
1022 self.sequence = seq
1023 self.thread_id = thread_id
1024 self.frame_id = frame_id
1025 self.expression = expression
1026 self.doExec = doExec
1027 self.doTrim = doTrim
1028
1029 def doIt(self, dbg):
1030 """ Converts request into python variable """
1031 try:
1032 result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec)
1033 xml = "<xml>"
Tor Norbye1aa2e092014-08-20 17:01:23 -07001034 xml += pydevd_vars.varToXML(result, self.expression, self.doTrim)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001035 xml += "</xml>"
1036 cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
1037 dbg.writer.addCommand(cmd)
1038 except:
1039 exc = GetExceptionTracebackStr()
1040 sys.stderr.write('%s\n' % (exc,))
1041 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1042 dbg.writer.addCommand(cmd)
1043
1044#=======================================================================================================================
Tor Norbyec667c1f2014-05-28 17:06:51 -07001045# InternalGetCompletions
1046#=======================================================================================================================
1047class InternalGetCompletions(InternalThreadCommand):
1048 """ Gets the completions in a given scope """
1049
1050 def __init__(self, seq, thread_id, frame_id, act_tok):
1051 self.sequence = seq
1052 self.thread_id = thread_id
1053 self.frame_id = frame_id
1054 self.act_tok = act_tok
1055
1056
1057 def doIt(self, dbg):
1058 """ Converts request into completions """
1059 try:
1060 remove_path = None
1061 try:
1062
1063 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1064 if frame is not None:
1065
Tor Norbyec667c1f2014-05-28 17:06:51 -07001066 msg = _pydev_completer.GenerateCompletionsAsXML(frame, self.act_tok)
1067
1068 cmd = dbg.cmdFactory.makeGetCompletionsMessage(self.sequence, msg)
1069 dbg.writer.addCommand(cmd)
1070 else:
1071 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "InternalGetCompletions: Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1072 dbg.writer.addCommand(cmd)
1073
1074
1075 finally:
1076 if remove_path is not None:
1077 sys.path.remove(remove_path)
1078
1079 except:
1080 exc = GetExceptionTracebackStr()
1081 sys.stderr.write('%s\n' % (exc,))
1082 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1083 dbg.writer.addCommand(cmd)
1084
Tor Norbye1aa2e092014-08-20 17:01:23 -07001085#=======================================================================================================================
1086# InternalGetBreakpointException
1087#=======================================================================================================================
1088class InternalGetBreakpointException(InternalThreadCommand):
1089 """ Send details of exception raised while evaluating conditional breakpoint """
1090 def __init__(self, thread_id, exc_type, stacktrace):
1091 self.sequence = 0
1092 self.thread_id = thread_id
1093 self.stacktrace = stacktrace
1094 self.exc_type = exc_type
1095
1096 def doIt(self, dbg):
1097 try:
1098 callstack = "<xml>"
1099
1100 makeValid = pydevd_vars.makeValidXmlValue
1101
1102 for filename, line, methodname, methodobj in self.stacktrace:
1103 if file_system_encoding.lower() != "utf-8" and hasattr(filename, "decode"):
1104 # filename is a byte string encoded using the file system encoding
1105 # convert it to utf8
1106 filename = filename.decode(file_system_encoding).encode("utf-8")
1107
1108 callstack += '<frame thread_id = "%s" file="%s" line="%s" name="%s" obj="%s" />' \
1109 % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj))
1110 callstack += "</xml>"
1111
1112 cmd = dbg.cmdFactory.makeSendBreakpointExceptionMessage(self.sequence, self.exc_type + "\t" + callstack)
1113 dbg.writer.addCommand(cmd)
1114 except:
1115 exc = GetExceptionTracebackStr()
1116 sys.stderr.write('%s\n' % (exc,))
1117 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Exception: " + exc)
1118 dbg.writer.addCommand(cmd)
1119
1120
1121#=======================================================================================================================
1122# InternalSendCurrExceptionTrace
1123#=======================================================================================================================
1124class InternalSendCurrExceptionTrace(InternalThreadCommand):
1125 """ Send details of the exception that was caught and where we've broken in.
1126 """
1127 def __init__(self, thread_id, arg, curr_frame_id):
1128 '''
1129 :param arg: exception type, description, traceback object
1130 '''
1131 self.sequence = 0
1132 self.thread_id = thread_id
1133 self.curr_frame_id = curr_frame_id
1134 self.arg = arg
1135
1136 def doIt(self, dbg):
1137 try:
1138 cmd = dbg.cmdFactory.makeSendCurrExceptionTraceMessage(self.sequence, self.thread_id, self.curr_frame_id, *self.arg)
1139 del self.arg
1140 dbg.writer.addCommand(cmd)
1141 except:
1142 exc = GetExceptionTracebackStr()
1143 sys.stderr.write('%s\n' % (exc,))
1144 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace: " + exc)
1145 dbg.writer.addCommand(cmd)
1146
1147#=======================================================================================================================
1148# InternalSendCurrExceptionTraceProceeded
1149#=======================================================================================================================
1150class InternalSendCurrExceptionTraceProceeded(InternalThreadCommand):
1151 """ Send details of the exception that was caught and where we've broken in.
1152 """
1153 def __init__(self, thread_id):
1154 self.sequence = 0
1155 self.thread_id = thread_id
1156
1157 def doIt(self, dbg):
1158 try:
1159 cmd = dbg.cmdFactory.makeSendCurrExceptionTraceProceededMessage(self.sequence, self.thread_id)
1160 dbg.writer.addCommand(cmd)
1161 except:
1162 exc = GetExceptionTracebackStr()
1163 sys.stderr.write('%s\n' % (exc,))
1164 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc)
1165 dbg.writer.addCommand(cmd)
1166
1167
1168#=======================================================================================================================
1169# InternalEvaluateConsoleExpression
1170#=======================================================================================================================
1171class InternalEvaluateConsoleExpression(InternalThreadCommand):
1172 """ Execute the given command in the debug console """
1173
1174 def __init__(self, seq, thread_id, frame_id, line):
1175 self.sequence = seq
1176 self.thread_id = thread_id
1177 self.frame_id = frame_id
1178 self.line = line
1179
1180 def doIt(self, dbg):
1181 """ Create an XML for console output, error and more (true/false)
1182 <xml>
1183 <output message=output_message></output>
1184 <error message=error_message></error>
1185 <more>true/false</more>
1186 </xml>
1187 """
1188 try:
1189 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1190 if frame is not None:
1191 console_message = pydevd_console.execute_console_command(frame, self.thread_id, self.frame_id, self.line)
1192 cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, console_message.toXML())
1193 else:
1194 from pydevd_console import ConsoleMessage
1195 console_message = ConsoleMessage()
1196 console_message.add_console_message(
Tor Norbyec3d3a902014-09-04 13:24:04 -07001197 pydevd_console.CONSOLE_ERROR,
1198 "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id),
Tor Norbye1aa2e092014-08-20 17:01:23 -07001199 )
1200 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, console_message.toXML())
1201 except:
1202 exc = GetExceptionTracebackStr()
1203 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1204 dbg.writer.addCommand(cmd)
1205
1206
1207#=======================================================================================================================
1208# InternalRunCustomOperation
1209#=======================================================================================================================
1210class InternalRunCustomOperation(InternalThreadCommand):
1211 """ Run a custom command on an expression
1212 """
1213 def __init__(self, seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname):
1214 self.sequence = seq
1215 self.thread_id = thread_id
1216 self.frame_id = frame_id
1217 self.scope = scope
1218 self.attrs = attrs
1219 self.style = style
1220 self.code_or_file = unquote_plus(encoded_code_or_file)
1221 self.fnname = fnname
1222
1223 def doIt(self, dbg):
1224 try:
1225 res = pydevd_vars.customOperation(self.thread_id, self.frame_id, self.scope, self.attrs,
1226 self.style, self.code_or_file, self.fnname)
1227 resEncoded = quote_plus(res)
1228 cmd = dbg.cmdFactory.makeCustomOperationMessage(self.sequence, resEncoded)
1229 dbg.writer.addCommand(cmd)
1230 except:
1231 exc = GetExceptionTracebackStr()
1232 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in running custom operation" + exc)
1233 dbg.writer.addCommand(cmd)
1234
1235
1236#=======================================================================================================================
1237# InternalConsoleGetCompletions
1238#=======================================================================================================================
1239class InternalConsoleGetCompletions(InternalThreadCommand):
1240 """ Fetch the completions in the debug console
1241 """
1242 def __init__(self, seq, thread_id, frame_id, act_tok):
1243 self.sequence = seq
1244 self.thread_id = thread_id
1245 self.frame_id = frame_id
1246 self.act_tok = act_tok
1247
1248 def doIt(self, dbg):
1249 """ Get completions and write back to the client
1250 """
1251 try:
1252 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1253 completions_xml = pydevd_console.get_completions(frame, self.act_tok)
1254 cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, completions_xml)
1255 dbg.writer.addCommand(cmd)
1256 except:
1257 exc = GetExceptionTracebackStr()
1258 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in fetching completions" + exc)
1259 dbg.writer.addCommand(cmd)
1260
Tor Norbyec667c1f2014-05-28 17:06:51 -07001261
1262#=======================================================================================================================
Tor Norbye3a2425a2013-11-04 10:16:08 -08001263# InternalConsoleExec
1264#=======================================================================================================================
1265class InternalConsoleExec(InternalThreadCommand):
1266 """ gets the value of a variable """
1267
1268 def __init__(self, seq, thread_id, frame_id, expression):
1269 self.sequence = seq
1270 self.thread_id = thread_id
1271 self.frame_id = frame_id
1272 self.expression = expression
1273
1274 def doIt(self, dbg):
1275 """ Converts request into python variable """
Tor Norbye3a2425a2013-11-04 10:16:08 -08001276 try:
1277 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001278 #don't trace new threads created by console command
1279 disable_trace_thread_modules()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001280
1281 result = pydevconsole.consoleExec(self.thread_id, self.frame_id, self.expression)
1282 xml = "<xml>"
1283 xml += pydevd_vars.varToXML(result, "")
1284 xml += "</xml>"
1285 cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
1286 dbg.writer.addCommand(cmd)
1287 except:
1288 exc = GetExceptionTracebackStr()
1289 sys.stderr.write('%s\n' % (exc,))
1290 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating console expression " + exc)
1291 dbg.writer.addCommand(cmd)
1292 finally:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001293 enable_trace_thread_modules()
1294
Tor Norbye3a2425a2013-11-04 10:16:08 -08001295 sys.stderr.flush()
1296 sys.stdout.flush()
1297
Tor Norbye3a2425a2013-11-04 10:16:08 -08001298
1299#=======================================================================================================================
1300# PydevdFindThreadById
1301#=======================================================================================================================
1302def PydevdFindThreadById(thread_id):
1303 try:
1304 # there was a deadlock here when I did not remove the tracing function when thread was dead
1305 threads = threading.enumerate()
1306 for i in threads:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001307 tid = GetThreadId(i)
1308 if thread_id == tid or thread_id.endswith('|' + tid):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001309 return i
1310
1311 sys.stderr.write("Could not find thread %s\n" % thread_id)
1312 sys.stderr.write("Available: %s\n" % [GetThreadId(t) for t in threads])
1313 sys.stderr.flush()
1314 except:
1315 traceback.print_exc()
1316
1317 return None
1318