blob: c7f39a16c483b715d633ba60fc9dd916d97b8405 [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 Norbye1aa2e092014-08-20 17:01:23 -070064from _pydev_imps import _pydev_time as time
Tor Norbye3a2425a2013-11-04 10:16:08 -080065
Tor Norbye1aa2e092014-08-20 17:01:23 -070066if USE_LIB_COPY:
67 import _pydev_threading as threading
68else:
69 import threading
70from _pydev_imps._pydev_socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
71from pydev_imports import _queue
Tor Norbye3a2425a2013-11-04 10:16:08 -080072
73try:
Tor Norbyec667c1f2014-05-28 17:06:51 -070074 from urllib import quote, quote_plus, unquote, unquote_plus
Tor Norbye3a2425a2013-11-04 10:16:08 -080075except:
Tor Norbyec667c1f2014-05-28 17:06:51 -070076 from urllib.parse import quote, quote_plus, unquote, unquote_plus #@Reimport @UnresolvedImport
77import pydevconsole
Tor Norbye3a2425a2013-11-04 10:16:08 -080078import pydevd_vars
Tor Norbye3a2425a2013-11-04 10:16:08 -080079import pydevd_tracing
80import pydevd_vm_type
81import pydevd_file_utils
82import traceback
Tor Norbyec667c1f2014-05-28 17:06:51 -070083from pydevd_utils import quote_smart as quote, compare_object_attrs, cmp_to_key, to_string
Tor Norbye92584642014-04-17 08:39:25 -070084import pydev_log
Tor Norbyec667c1f2014-05-28 17:06:51 -070085import _pydev_completer
Tor Norbye3a2425a2013-11-04 10:16:08 -080086
87from pydevd_tracing import GetExceptionTracebackStr
Tor Norbye1aa2e092014-08-20 17:01:23 -070088import pydevd_console
89from pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules
Tor Norbyec667c1f2014-05-28 17:06:51 -070090
Tor Norbye3a2425a2013-11-04 10:16:08 -080091
Tor Norbye3a2425a2013-11-04 10:16:08 -080092
93CMD_RUN = 101
94CMD_LIST_THREADS = 102
95CMD_THREAD_CREATE = 103
96CMD_THREAD_KILL = 104
97CMD_THREAD_SUSPEND = 105
98CMD_THREAD_RUN = 106
99CMD_STEP_INTO = 107
100CMD_STEP_OVER = 108
101CMD_STEP_RETURN = 109
102CMD_GET_VARIABLE = 110
103CMD_SET_BREAK = 111
104CMD_REMOVE_BREAK = 112
105CMD_EVALUATE_EXPRESSION = 113
106CMD_GET_FRAME = 114
107CMD_EXEC_EXPRESSION = 115
108CMD_WRITE_TO_CONSOLE = 116
109CMD_CHANGE_VARIABLE = 117
110CMD_RUN_TO_LINE = 118
111CMD_RELOAD_CODE = 119
112CMD_GET_COMPLETIONS = 120
Tor Norbye1aa2e092014-08-20 17:01:23 -0700113
114# Note: renumbered (conflicted on merge)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800115CMD_CONSOLE_EXEC = 121
116CMD_ADD_EXCEPTION_BREAK = 122
117CMD_REMOVE_EXCEPTION_BREAK = 123
118CMD_LOAD_SOURCE = 124
119CMD_ADD_DJANGO_EXCEPTION_BREAK = 125
120CMD_REMOVE_DJANGO_EXCEPTION_BREAK = 126
121CMD_SET_NEXT_STATEMENT = 127
122CMD_SMART_STEP_INTO = 128
123CMD_EXIT = 129
124CMD_SIGNATURE_CALL_TRACE = 130
Tor Norbye1aa2e092014-08-20 17:01:23 -0700125
126
127
128CMD_SET_PY_EXCEPTION = 131
129CMD_GET_FILE_CONTENTS = 132
130CMD_SET_PROPERTY_TRACE = 133
131# Pydev debug console commands
132CMD_EVALUATE_CONSOLE_EXPRESSION = 134
133CMD_RUN_CUSTOM_OPERATION = 135
134CMD_GET_BREAKPOINT_EXCEPTION = 136
135CMD_STEP_CAUGHT_EXCEPTION = 137
136CMD_SEND_CURR_EXCEPTION_TRACE = 138
137CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED = 139
138CMD_IGNORE_THROWN_EXCEPTION_AT = 140
139CMD_ENABLE_DONT_TRACE = 141
140
141
142
Tor Norbye3a2425a2013-11-04 10:16:08 -0800143CMD_VERSION = 501
144CMD_RETURN = 502
145CMD_ERROR = 901
146
147ID_TO_MEANING = {
148 '101':'CMD_RUN',
149 '102':'CMD_LIST_THREADS',
150 '103':'CMD_THREAD_CREATE',
151 '104':'CMD_THREAD_KILL',
152 '105':'CMD_THREAD_SUSPEND',
153 '106':'CMD_THREAD_RUN',
154 '107':'CMD_STEP_INTO',
155 '108':'CMD_STEP_OVER',
156 '109':'CMD_STEP_RETURN',
157 '110':'CMD_GET_VARIABLE',
158 '111':'CMD_SET_BREAK',
159 '112':'CMD_REMOVE_BREAK',
160 '113':'CMD_EVALUATE_EXPRESSION',
161 '114':'CMD_GET_FRAME',
162 '115':'CMD_EXEC_EXPRESSION',
163 '116':'CMD_WRITE_TO_CONSOLE',
164 '117':'CMD_CHANGE_VARIABLE',
165 '118':'CMD_RUN_TO_LINE',
166 '119':'CMD_RELOAD_CODE',
167 '120':'CMD_GET_COMPLETIONS',
168 '121':'CMD_CONSOLE_EXEC',
169 '122':'CMD_ADD_EXCEPTION_BREAK',
170 '123':'CMD_REMOVE_EXCEPTION_BREAK',
171 '124':'CMD_LOAD_SOURCE',
172 '125':'CMD_ADD_DJANGO_EXCEPTION_BREAK',
173 '126':'CMD_REMOVE_DJANGO_EXCEPTION_BREAK',
174 '127':'CMD_SET_NEXT_STATEMENT',
175 '128':'CMD_SMART_STEP_INTO',
176 '129': 'CMD_EXIT',
177 '130': 'CMD_SIGNATURE_CALL_TRACE',
Tor Norbye1aa2e092014-08-20 17:01:23 -0700178
179 '131': 'CMD_SET_PY_EXCEPTION',
180 '132': 'CMD_GET_FILE_CONTENTS',
181 '133': 'CMD_SET_PROPERTY_TRACE',
182 '134': 'CMD_EVALUATE_CONSOLE_EXPRESSION',
183 '135': 'CMD_RUN_CUSTOM_OPERATION',
184 '136': 'CMD_GET_BREAKPOINT_EXCEPTION',
185 '137': 'CMD_STEP_CAUGHT_EXCEPTION',
186 '138': 'CMD_SEND_CURR_EXCEPTION_TRACE',
187 '139': 'CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED',
188 '140': 'CMD_IGNORE_THROWN_EXCEPTION_AT',
189 '141': 'CMD_ENABLE_DONT_TRACE',
190
Tor Norbye3a2425a2013-11-04 10:16:08 -0800191 '501':'CMD_VERSION',
192 '502':'CMD_RETURN',
193 '901':'CMD_ERROR',
194 }
195
196MAX_IO_MSG_SIZE = 1000 #if the io is too big, we'll not send all (could make the debugger too non-responsive)
197#this number can be changed if there's need to do so
198
199VERSION_STRING = "@@BUILD_NUMBER@@"
200
Tor Norbyec667c1f2014-05-28 17:06:51 -0700201from _pydev_filesystem_encoding import getfilesystemencoding
202file_system_encoding = getfilesystemencoding()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800203
204#--------------------------------------------------------------------------------------------------- UTILITIES
205
206#=======================================================================================================================
207# PydevdLog
208#=======================================================================================================================
209def PydevdLog(level, *args):
210 """ levels are:
211 0 most serious warnings/errors
212 1 warnings/significant events
213 2 informational trace
214 """
215 if level <= DebugInfoHolder.DEBUG_TRACE_LEVEL:
216 #yes, we can have errors printing if the console of the program has been finished (and we're still trying to print something)
217 try:
218 sys.stderr.write('%s\n' % (args,))
219 except:
220 pass
221
222#=======================================================================================================================
223# GlobalDebuggerHolder
224#=======================================================================================================================
225class GlobalDebuggerHolder:
226 '''
227 Holder for the global debugger.
228 '''
229 globalDbg = None
230
231#=======================================================================================================================
232# GetGlobalDebugger
233#=======================================================================================================================
234def GetGlobalDebugger():
235 return GlobalDebuggerHolder.globalDbg
236
237#=======================================================================================================================
238# SetGlobalDebugger
239#=======================================================================================================================
240def SetGlobalDebugger(dbg):
241 GlobalDebuggerHolder.globalDbg = dbg
242
243
244#------------------------------------------------------------------- ACTUAL COMM
245
246#=======================================================================================================================
247# PyDBDaemonThread
248#=======================================================================================================================
249class PyDBDaemonThread(threading.Thread):
250
251 def __init__(self):
252 threading.Thread.__init__(self)
253 self.setDaemon(True)
254 self.killReceived = False
255 self.dontTraceMe = True
256
257 def run(self):
258 if sys.platform.startswith("java"):
259 import org.python.core as PyCore #@UnresolvedImport
260 ss = PyCore.PySystemState()
261 # Note: Py.setSystemState() affects only the current thread.
262 PyCore.Py.setSystemState(ss)
263
264 self.OnRun()
265
266 def OnRun(self):
267 raise NotImplementedError('Should be reimplemented by: %s' % self.__class__)
268
269 def doKillPydevThread(self):
270 #that was not working very well because jython gave some socket errors
271 self.killReceived = True
272
Tor Norbye3a2425a2013-11-04 10:16:08 -0800273 def stopTrace(self):
274 if self.dontTraceMe:
275 pydevd_tracing.SetTrace(None) # no debugging on this thread
276
277
278#=======================================================================================================================
279# ReaderThread
280#=======================================================================================================================
281class ReaderThread(PyDBDaemonThread):
282 """ reader thread reads and dispatches commands in an infinite loop """
283
284 def __init__(self, sock):
285 PyDBDaemonThread.__init__(self)
286 self.sock = sock
287 self.setName("pydevd.Reader")
288
289
290 def doKillPydevThread(self):
291 #We must close the socket so that it doesn't stay halted there.
292 self.killReceived = True
293 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700294 self.sock.shutdown(SHUT_RD) #shutdown the socket for read
Tor Norbye3a2425a2013-11-04 10:16:08 -0800295 except:
296 #just ignore that
297 pass
298
299 def OnRun(self):
300 self.stopTrace()
301 buffer = ""
302 try:
303
304 while not self.killReceived:
305 try:
306 r = self.sock.recv(1024)
307 except:
308 if not self.killReceived:
309 self.handleExcept()
310 return #Finished communication.
Tor Norbyec667c1f2014-05-28 17:06:51 -0700311
312 #Note: the java backend is always expected to pass utf-8 encoded strings. We now work with unicode
313 #internally and thus, we may need to convert to the actual encoding where needed (i.e.: filenames
314 #on python 2 may need to be converted to the filesystem encoding).
315 if hasattr(r, 'decode'):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800316 r = r.decode('utf-8')
317
318 buffer += r
319 if DebugInfoHolder.DEBUG_RECORD_SOCKET_READS:
320 pydev_log.debug('received >>%s<<\n' % (buffer,))
321
322 if len(buffer) == 0:
323 self.handleExcept()
324 break
325 while buffer.find('\n') != -1:
326 command, buffer = buffer.split('\n', 1)
Tor Norbye1fff8e22014-03-10 13:13:45 -0700327
Tor Norbye3a2425a2013-11-04 10:16:08 -0800328 args = command.split('\t', 2)
329 try:
Tor Norbye1fff8e22014-03-10 13:13:45 -0700330 cmd_id = int(args[0])
331 pydev_log.debug('Received command: %s %s\n' % (ID_TO_MEANING.get(str(cmd_id), '???'), command,))
332 self.processCommand(cmd_id, int(args[1]), args[2])
Tor Norbye3a2425a2013-11-04 10:16:08 -0800333 except:
334 traceback.print_exc()
335 sys.stderr.write("Can't process net command: %s\n" % command)
336 sys.stderr.flush()
337
338 except:
339 traceback.print_exc()
340 self.handleExcept()
341
342
343 def handleExcept(self):
344 GlobalDebuggerHolder.globalDbg.FinishDebuggingSession()
345
346 def processCommand(self, cmd_id, seq, text):
347 GlobalDebuggerHolder.globalDbg.processNetCommand(cmd_id, seq, text)
348
349
350#----------------------------------------------------------------------------------- SOCKET UTILITIES - WRITER
351#=======================================================================================================================
352# WriterThread
353#=======================================================================================================================
354class WriterThread(PyDBDaemonThread):
355 """ writer thread writes out the commands in an infinite loop """
356 def __init__(self, sock):
357 PyDBDaemonThread.__init__(self)
358 self.setDaemon(False) #writer isn't daemon to be able to deliver all messages after main thread terminated
359 self.sock = sock
360 self.setName("pydevd.Writer")
361 self.cmdQueue = _queue.Queue()
362 if pydevd_vm_type.GetVmType() == 'python':
363 self.timeout = 0
364 else:
365 self.timeout = 0.1
366
367 def addCommand(self, cmd):
368 """ cmd is NetCommand """
369 if not self.killReceived: #we don't take new data after everybody die
370 self.cmdQueue.put(cmd)
371
372 def OnRun(self):
373 """ just loop and write responses """
374
375 self.stopTrace()
376 try:
377 while True:
378 try:
379 try:
380 cmd = self.cmdQueue.get(1, 0.1)
381 except _queue.Empty:
382 if self.killReceived:
383 try:
384 self.sock.shutdown(SHUT_WR)
385 self.sock.close()
386 except:
387 pass
Tor Norbye3a2425a2013-11-04 10:16:08 -0800388
389 return #break if queue is empty and killReceived
390 else:
391 continue
392 except:
393 #PydevdLog(0, 'Finishing debug communication...(1)')
394 #when liberating the thread here, we could have errors because we were shutting down
395 #but the thread was still not liberated
396 return
397 out = cmd.getOutgoing()
398
399 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700400 out_message = 'sending cmd --> '
401 out_message += "%20s" % ID_TO_MEANING.get(out[:3], 'UNKNOWN')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800402 out_message += ' '
Tor Norbyec667c1f2014-05-28 17:06:51 -0700403 out_message += unquote(unquote(out)).replace('\n', ' ')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800404 try:
405 sys.stderr.write('%s\n' % (out_message,))
406 except:
407 pass
408
409 if IS_PY3K:
410 out = bytearray(out, 'utf-8')
411 self.sock.send(out) #TODO: this does not guarantee that all message are sent (and jython does not have a send all)
412 if cmd.id == CMD_EXIT:
413 break
414 if time is None:
415 break #interpreter shutdown
416 time.sleep(self.timeout)
417 except Exception:
418 GlobalDebuggerHolder.globalDbg.FinishDebuggingSession()
419 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 0:
420 traceback.print_exc()
421
422
423
424
425#--------------------------------------------------- CREATING THE SOCKET THREADS
426
427#=======================================================================================================================
428# StartServer
429#=======================================================================================================================
430def StartServer(port):
431 """ binds to a port, waits for the debugger to connect """
432 s = socket(AF_INET, SOCK_STREAM)
433 s.bind(('', port))
434 s.listen(1)
435 newSock, _addr = s.accept()
436 return newSock
437
438#=======================================================================================================================
439# StartClient
440#=======================================================================================================================
441def StartClient(host, port):
442 """ connects to a host/port """
443 PydevdLog(1, "Connecting to ", host, ":", str(port))
444
445 s = socket(AF_INET, SOCK_STREAM)
446
Tor Norbye2e5965e2014-07-25 12:24:15 -0700447 MAX_TRIES = 100
Tor Norbye3a2425a2013-11-04 10:16:08 -0800448 i = 0
449 while i<MAX_TRIES:
450 try:
451 s.connect((host, port))
452 except:
453 i+=1
454 time.sleep(0.2)
455 continue
456 PydevdLog(1, "Connected.")
457 return s
458
459 sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
460 sys.stderr.flush()
461 traceback.print_exc()
462 sys.exit(1) #TODO: is it safe?
463
464
465
466#------------------------------------------------------------------------------------ MANY COMMUNICATION STUFF
467
468#=======================================================================================================================
469# NetCommand
470#=======================================================================================================================
471class NetCommand:
472 """ Commands received/sent over the network.
473
474 Command can represent command received from the debugger,
475 or one to be sent by daemon.
476 """
477 next_seq = 0 # sequence numbers
478
479 def __init__(self, id, seq, text):
480 """ smart handling of paramaters
481 if sequence is 0, new sequence will be generated
482 if text has carriage returns they'll be replaced"""
483 self.id = id
484 if (seq == 0): seq = self.getNextSeq()
485 self.seq = seq
486 self.text = text
487 self.outgoing = self.makeMessage(id, seq, text)
488
489 def getNextSeq(self):
490 """ returns next sequence number """
491 NetCommand.next_seq += 2
492 return NetCommand.next_seq
493
494 def getOutgoing(self):
495 """ returns the outgoing message"""
496 return self.outgoing
497
498 def makeMessage(self, cmd, seq, payload):
499 encoded = quote(to_string(payload), '/<>_=" \t')
500 return str(cmd) + '\t' + str(seq) + '\t' + encoded + "\n"
501
502#=======================================================================================================================
503# NetCommandFactory
504#=======================================================================================================================
505class NetCommandFactory:
506
507 def __init_(self):
508 self.next_seq = 0
509
510 def threadToXML(self, thread):
511 """ thread information as XML """
512 name = pydevd_vars.makeValidXmlValue(thread.getName())
513 cmdText = '<thread name="%s" id="%s" />' % (quote(name), GetThreadId(thread))
514 return cmdText
515
516 def makeErrorMessage(self, seq, text):
517 cmd = NetCommand(CMD_ERROR, seq, text)
518 if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2:
519 sys.stderr.write("Error: %s" % (text,))
520 return cmd
521
522 def makeThreadCreatedMessage(self, thread):
523 cmdText = "<xml>" + self.threadToXML(thread) + "</xml>"
524 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
525
Tor Norbyec667c1f2014-05-28 17:06:51 -0700526
527 def makeCustomFrameCreatedMessage(self, frameId, frameDescription):
528 frameDescription = pydevd_vars.makeValidXmlValue(frameDescription)
529 cmdText = '<xml><thread name="%s" id="%s"/></xml>' % (frameDescription, frameId)
530 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
531
532
Tor Norbye3a2425a2013-11-04 10:16:08 -0800533 def makeListThreadsMessage(self, seq):
534 """ returns thread listing as XML """
535 try:
536 t = threading.enumerate()
537 cmdText = "<xml>"
538 for i in t:
539 if t.isAlive():
540 cmdText += self.threadToXML(i)
541 cmdText += "</xml>"
542 return NetCommand(CMD_RETURN, seq, cmdText)
543 except:
544 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
545
546 def makeVariableChangedMessage(self, seq, payload):
547 # notify debugger that value was changed successfully
548 return NetCommand(CMD_RETURN, seq, payload)
549
550 def makeIoMessage(self, v, ctx, dbg=None):
551 '''
552 @param v: the message to pass to the debug server
553 @param ctx: 1 for stdio 2 for stderr
554 @param dbg: If not none, add to the writer
555 '''
556
557 try:
558 if len(v) > MAX_IO_MSG_SIZE:
559 v = v[0:MAX_IO_MSG_SIZE]
560 v += '...'
561
562 v = pydevd_vars.makeValidXmlValue(quote(v, '/>_= \t'))
563 net = NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '<xml><io s="%s" ctx="%s"/></xml>' % (v, ctx))
564 except:
565 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
566
567 if dbg:
568 dbg.writer.addCommand(net)
569
570 return net
571
572 def makeVersionMessage(self, seq):
573 try:
574 return NetCommand(CMD_VERSION, seq, VERSION_STRING)
575 except:
576 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
577
578 def makeThreadKilledMessage(self, id):
579 try:
580 return NetCommand(CMD_THREAD_KILL, 0, str(id))
581 except:
582 return self.makeErrorMessage(0, GetExceptionTracebackStr())
583
Tor Norbye1aa2e092014-08-20 17:01:23 -0700584 def makeThreadSuspendStr(self, thread_id, frame, stop_reason, message):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800585 """ <xml>
586 <thread id="id" stop_reason="reason">
587 <frame id="id" name="functionName " file="file" line="line">
588 <var variable stuffff....
589 </frame>
590 </thread>
Tor Norbye1aa2e092014-08-20 17:01:23 -0700591 """
592 cmdTextList = ["<xml>"]
593
594 if message:
595 message = pydevd_vars.makeValidXmlValue(str(message))
596
597 cmdTextList.append('<thread id="%s" stop_reason="%s" message="%s">' % (thread_id, stop_reason, message))
598
599 curFrame = frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800600 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700601 while curFrame:
602 #print cmdText
603 myId = str(id(curFrame))
604 #print "id is ", myId
Tor Norbye3a2425a2013-11-04 10:16:08 -0800605
Tor Norbye1aa2e092014-08-20 17:01:23 -0700606 if curFrame.f_code is None:
607 break #Iron Python sometimes does not have it!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800608
Tor Norbye1aa2e092014-08-20 17:01:23 -0700609 myName = curFrame.f_code.co_name #method name (if in method) or ? if global
610 if myName is None:
611 break #Iron Python sometimes does not have it!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800612
Tor Norbye1aa2e092014-08-20 17:01:23 -0700613 #print "name is ", myName
Tor Norbye3a2425a2013-11-04 10:16:08 -0800614
Tor Norbye1aa2e092014-08-20 17:01:23 -0700615 filename, base = pydevd_file_utils.GetFilenameAndBase(curFrame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800616
Tor Norbye1aa2e092014-08-20 17:01:23 -0700617 myFile = pydevd_file_utils.NormFileToClient(filename)
618 if file_system_encoding.lower() != "utf-8" and hasattr(myFile, "decode"):
619 # myFile is a byte string encoded using the file system encoding
620 # convert it to utf8
621 myFile = myFile.decode(file_system_encoding).encode("utf-8")
Tor Norbye3a2425a2013-11-04 10:16:08 -0800622
Tor Norbye1aa2e092014-08-20 17:01:23 -0700623 #print "file is ", myFile
624 #myFile = inspect.getsourcefile(curFrame) or inspect.getfile(frame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800625
Tor Norbye1aa2e092014-08-20 17:01:23 -0700626 myLine = str(curFrame.f_lineno)
627 #print "line is ", myLine
Tor Norbye3a2425a2013-11-04 10:16:08 -0800628
Tor Norbye1aa2e092014-08-20 17:01:23 -0700629 #the variables are all gotten 'on-demand'
630 #variables = pydevd_vars.frameVarsToXML(curFrame.f_locals)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800631
Tor Norbye1aa2e092014-08-20 17:01:23 -0700632 variables = ''
633 cmdTextList.append('<frame id="%s" name="%s" ' % (myId , pydevd_vars.makeValidXmlValue(myName)))
634 cmdTextList.append('file="%s" line="%s">"' % (quote(myFile, '/>_= \t'), myLine))
635 cmdTextList.append(variables)
636 cmdTextList.append("</frame>")
637 curFrame = curFrame.f_back
638 except :
639 traceback.print_exc()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800640
Tor Norbye1aa2e092014-08-20 17:01:23 -0700641 cmdTextList.append("</thread></xml>")
642 return ''.join(cmdTextList)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800643
Tor Norbye1aa2e092014-08-20 17:01:23 -0700644 def makeThreadSuspendMessage(self, thread_id, frame, stop_reason, message):
645 try:
646 return NetCommand(CMD_THREAD_SUSPEND, 0, self.makeThreadSuspendStr(thread_id, frame, stop_reason, message))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800647 except:
648 return self.makeErrorMessage(0, GetExceptionTracebackStr())
649
650 def makeThreadRunMessage(self, id, reason):
651 try:
652 return NetCommand(CMD_THREAD_RUN, 0, str(id) + "\t" + str(reason))
653 except:
654 return self.makeErrorMessage(0, GetExceptionTracebackStr())
655
656 def makeGetVariableMessage(self, seq, payload):
657 try:
658 return NetCommand(CMD_GET_VARIABLE, seq, payload)
659 except Exception:
660 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
661
662 def makeGetFrameMessage(self, seq, payload):
663 try:
664 return NetCommand(CMD_GET_FRAME, seq, payload)
665 except Exception:
666 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
667
668
669 def makeEvaluateExpressionMessage(self, seq, payload):
670 try:
671 return NetCommand(CMD_EVALUATE_EXPRESSION, seq, payload)
672 except Exception:
673 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
674
675 def makeGetCompletionsMessage(self, seq, payload):
676 try:
677 return NetCommand(CMD_GET_COMPLETIONS, seq, payload)
678 except Exception:
679 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
680
Tor Norbye1aa2e092014-08-20 17:01:23 -0700681 def makeGetFileContents(self, seq, payload):
682 try:
683 return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload)
684 except Exception:
685 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
686
687 def makeSendBreakpointExceptionMessage(self, seq, payload):
688 try:
689 return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload)
690 except Exception:
691 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
692
693 def makeSendCurrExceptionTraceMessage(self, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj):
694 try:
695 while trace_obj.tb_next is not None:
696 trace_obj = trace_obj.tb_next
697
698 exc_type = pydevd_vars.makeValidXmlValue(str(exc_type)).replace('\t', ' ') or 'exception: type unknown'
699 exc_desc = pydevd_vars.makeValidXmlValue(str(exc_desc)).replace('\t', ' ') or 'exception: no description'
700
701 payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + \
702 self.makeThreadSuspendStr(thread_id, trace_obj.tb_frame, CMD_SEND_CURR_EXCEPTION_TRACE, '')
703
704 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload)
705 except Exception:
706 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
707
708 def makeSendCurrExceptionTraceProceededMessage(self, seq, thread_id):
709 try:
710 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id))
711 except:
712 return self.makeErrorMessage(0, GetExceptionTracebackStr())
713
714 def makeSendConsoleMessage(self, seq, payload):
715 try:
716 return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload)
717 except Exception:
718 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
719
720 def makeCustomOperationMessage(self, seq, payload):
721 try:
722 return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload)
723 except Exception:
724 return self.makeErrorMessage(seq, GetExceptionTracebackStr())
725
Tor Norbye3a2425a2013-11-04 10:16:08 -0800726 def makeLoadSourceMessage(self, seq, source, dbg=None):
727 try:
728 net = NetCommand(CMD_LOAD_SOURCE, seq, '%s' % source)
729
730 except:
731 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
732
733 if dbg:
734 dbg.writer.addCommand(net)
735 return net
736
737 def makeExitMessage(self):
738 try:
739 net = NetCommand(CMD_EXIT, 0, '')
740
741 except:
742 net = self.makeErrorMessage(0, GetExceptionTracebackStr())
743
744 return net
745
746INTERNAL_TERMINATE_THREAD = 1
747INTERNAL_SUSPEND_THREAD = 2
748
749
750#=======================================================================================================================
751# InternalThreadCommand
752#=======================================================================================================================
753class InternalThreadCommand:
754 """ internal commands are generated/executed by the debugger.
755
756 The reason for their existence is that some commands have to be executed
757 on specific threads. These are the InternalThreadCommands that get
758 get posted to PyDB.cmdQueue.
759 """
760
761 def canBeExecutedBy(self, thread_id):
762 '''By default, it must be in the same thread to be executed
763 '''
Tor Norbye1aa2e092014-08-20 17:01:23 -0700764 return self.thread_id == thread_id or self.thread_id.endswith('|' + thread_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800765
766 def doIt(self, dbg):
767 raise NotImplementedError("you have to override doIt")
768
Tor Norbyec667c1f2014-05-28 17:06:51 -0700769
770class ReloadCodeCommand(InternalThreadCommand):
771
772
773 def __init__(self, module_name, thread_id):
774 self.thread_id = thread_id
775 self.module_name = module_name
776 self.executed = False
777 self.lock = threading.Lock()
778
779
780 def canBeExecutedBy(self, thread_id):
781 if self.thread_id == '*':
782 return True #Any thread can execute it!
783
784 return InternalThreadCommand.canBeExecutedBy(self, thread_id)
785
786
787 def doIt(self, dbg):
788 self.lock.acquire()
789 try:
790 if self.executed:
791 return
792 self.executed = True
793 finally:
794 self.lock.release()
795
796 module_name = self.module_name
797 if not DictContains(sys.modules, module_name):
798 if '.' in module_name:
799 new_module_name = module_name.split('.')[-1]
800 if DictContains(sys.modules, new_module_name):
801 module_name = new_module_name
802
803 if not DictContains(sys.modules, module_name):
804 sys.stderr.write('pydev debugger: Unable to find module to reload: "' + module_name + '".\n')
805 # Too much info...
806 # sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n')
807
808 else:
809 sys.stderr.write('pydev debugger: Start reloading module: "' + module_name + '" ... \n')
810 import pydevd_reload
811 if pydevd_reload.xreload(sys.modules[module_name]):
812 sys.stderr.write('pydev debugger: reload finished\n')
813 else:
814 sys.stderr.write('pydev debugger: reload finished without applying any change\n')
815
816
Tor Norbye3a2425a2013-11-04 10:16:08 -0800817#=======================================================================================================================
818# InternalTerminateThread
819#=======================================================================================================================
820class InternalTerminateThread(InternalThreadCommand):
821 def __init__(self, thread_id):
822 self.thread_id = thread_id
823
824 def doIt(self, dbg):
825 PydevdLog(1, "killing ", str(self.thread_id))
826 cmd = dbg.cmdFactory.makeThreadKilledMessage(self.thread_id)
827 dbg.writer.addCommand(cmd)
828
829
830#=======================================================================================================================
831# InternalRunThread
832#=======================================================================================================================
833class InternalRunThread(InternalThreadCommand):
834 def __init__(self, thread_id):
835 self.thread_id = thread_id
836
837 def doIt(self, dbg):
838 t = PydevdFindThreadById(self.thread_id)
839 if t:
840 t.additionalInfo.pydev_step_cmd = None
841 t.additionalInfo.pydev_step_stop = None
842 t.additionalInfo.pydev_state = STATE_RUN
843
844
845#=======================================================================================================================
846# InternalStepThread
847#=======================================================================================================================
848class InternalStepThread(InternalThreadCommand):
849 def __init__(self, thread_id, cmd_id):
850 self.thread_id = thread_id
851 self.cmd_id = cmd_id
852
853 def doIt(self, dbg):
854 t = PydevdFindThreadById(self.thread_id)
855 if t:
856 t.additionalInfo.pydev_step_cmd = self.cmd_id
857 t.additionalInfo.pydev_state = STATE_RUN
858
859#=======================================================================================================================
860# InternalSetNextStatementThread
861#=======================================================================================================================
862class InternalSetNextStatementThread(InternalThreadCommand):
863 def __init__(self, thread_id, cmd_id, line, func_name):
864 self.thread_id = thread_id
865 self.cmd_id = cmd_id
866 self.line = line
867 self.func_name = func_name
868
869 def doIt(self, dbg):
870 t = PydevdFindThreadById(self.thread_id)
871 if t:
872 t.additionalInfo.pydev_step_cmd = self.cmd_id
873 t.additionalInfo.pydev_next_line = int(self.line)
874 t.additionalInfo.pydev_func_name = self.func_name
875 t.additionalInfo.pydev_state = STATE_RUN
876
877
878#=======================================================================================================================
879# InternalGetVariable
880#=======================================================================================================================
881class InternalGetVariable(InternalThreadCommand):
882 """ gets the value of a variable """
883 def __init__(self, seq, thread_id, frame_id, scope, attrs):
884 self.sequence = seq
885 self.thread_id = thread_id
886 self.frame_id = frame_id
887 self.scope = scope
888 self.attributes = attrs
889
890 def doIt(self, dbg):
891 """ Converts request into python variable """
892 try:
893 xml = "<xml>"
894 valDict = pydevd_vars.resolveCompoundVariable(self.thread_id, self.frame_id, self.scope, self.attributes)
895 if valDict is None:
896 valDict = {}
897
898 keys = valDict.keys()
899 if hasattr(keys, 'sort'):
900 keys.sort(compare_object_attrs) #Python 3.0 does not have it
901 else:
902 if IS_PY3K:
903 keys = sorted(keys, key=cmp_to_key(compare_object_attrs)) #Jython 2.1 does not have it (and all must be compared as strings).
904 else:
905 keys = sorted(keys, cmp=compare_object_attrs) #Jython 2.1 does not have it (and all must be compared as strings).
906
907 for k in keys:
908 xml += pydevd_vars.varToXML(valDict[k], to_string(k))
909
910 xml += "</xml>"
911 cmd = dbg.cmdFactory.makeGetVariableMessage(self.sequence, xml)
912 dbg.writer.addCommand(cmd)
913 except Exception:
914 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error resolving variables " + GetExceptionTracebackStr())
915 dbg.writer.addCommand(cmd)
916
917
918#=======================================================================================================================
919# InternalChangeVariable
920#=======================================================================================================================
921class InternalChangeVariable(InternalThreadCommand):
922 """ changes the value of a variable """
923 def __init__(self, seq, thread_id, frame_id, scope, attr, expression):
924 self.sequence = seq
925 self.thread_id = thread_id
926 self.frame_id = frame_id
927 self.scope = scope
928 self.attr = attr
929 self.expression = expression
930
931 def doIt(self, dbg):
932 """ Converts request into python variable """
933 try:
934 result = pydevd_vars.changeAttrExpression(self.thread_id, self.frame_id, self.attr, self.expression)
935 xml = "<xml>"
936 xml += pydevd_vars.varToXML(result, "")
937 xml += "</xml>"
938 cmd = dbg.cmdFactory.makeVariableChangedMessage(self.sequence, xml)
939 dbg.writer.addCommand(cmd)
940 except Exception:
941 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error changing variable attr:%s expression:%s traceback:%s" % (self.attr, self.expression, GetExceptionTracebackStr()))
942 dbg.writer.addCommand(cmd)
943
944
945#=======================================================================================================================
946# InternalGetFrame
947#=======================================================================================================================
948class InternalGetFrame(InternalThreadCommand):
949 """ gets the value of a variable """
950 def __init__(self, seq, thread_id, frame_id):
951 self.sequence = seq
952 self.thread_id = thread_id
953 self.frame_id = frame_id
954
955 def doIt(self, dbg):
956 """ Converts request into python variable """
957 try:
958 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
959 if frame is not None:
960 xml = "<xml>"
961 xml += pydevd_vars.frameVarsToXML(frame.f_locals)
962 del frame
963 xml += "</xml>"
964 cmd = dbg.cmdFactory.makeGetFrameMessage(self.sequence, xml)
965 dbg.writer.addCommand(cmd)
966 else:
967 #pydevd_vars.dumpFrames(self.thread_id)
968 #don't print this error: frame not found: means that the client is not synchronized (but that's ok)
969 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
970 dbg.writer.addCommand(cmd)
971 except:
972 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error resolving frame: %s from thread: %s" % (self.frame_id, self.thread_id))
973 dbg.writer.addCommand(cmd)
974
975
976#=======================================================================================================================
977# InternalEvaluateExpression
978#=======================================================================================================================
979class InternalEvaluateExpression(InternalThreadCommand):
980 """ gets the value of a variable """
981
982 def __init__(self, seq, thread_id, frame_id, expression, doExec, doTrim):
983 self.sequence = seq
984 self.thread_id = thread_id
985 self.frame_id = frame_id
986 self.expression = expression
987 self.doExec = doExec
988 self.doTrim = doTrim
989
990 def doIt(self, dbg):
991 """ Converts request into python variable """
992 try:
993 result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec)
994 xml = "<xml>"
Tor Norbye1aa2e092014-08-20 17:01:23 -0700995 xml += pydevd_vars.varToXML(result, self.expression, self.doTrim)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800996 xml += "</xml>"
997 cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
998 dbg.writer.addCommand(cmd)
999 except:
1000 exc = GetExceptionTracebackStr()
1001 sys.stderr.write('%s\n' % (exc,))
1002 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1003 dbg.writer.addCommand(cmd)
1004
1005#=======================================================================================================================
Tor Norbyec667c1f2014-05-28 17:06:51 -07001006# InternalGetCompletions
1007#=======================================================================================================================
1008class InternalGetCompletions(InternalThreadCommand):
1009 """ Gets the completions in a given scope """
1010
1011 def __init__(self, seq, thread_id, frame_id, act_tok):
1012 self.sequence = seq
1013 self.thread_id = thread_id
1014 self.frame_id = frame_id
1015 self.act_tok = act_tok
1016
1017
1018 def doIt(self, dbg):
1019 """ Converts request into completions """
1020 try:
1021 remove_path = None
1022 try:
1023
1024 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1025 if frame is not None:
1026
Tor Norbyec667c1f2014-05-28 17:06:51 -07001027 msg = _pydev_completer.GenerateCompletionsAsXML(frame, self.act_tok)
1028
1029 cmd = dbg.cmdFactory.makeGetCompletionsMessage(self.sequence, msg)
1030 dbg.writer.addCommand(cmd)
1031 else:
1032 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "InternalGetCompletions: Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1033 dbg.writer.addCommand(cmd)
1034
1035
1036 finally:
1037 if remove_path is not None:
1038 sys.path.remove(remove_path)
1039
1040 except:
1041 exc = GetExceptionTracebackStr()
1042 sys.stderr.write('%s\n' % (exc,))
1043 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1044 dbg.writer.addCommand(cmd)
1045
Tor Norbye1aa2e092014-08-20 17:01:23 -07001046#=======================================================================================================================
1047# InternalGetBreakpointException
1048#=======================================================================================================================
1049class InternalGetBreakpointException(InternalThreadCommand):
1050 """ Send details of exception raised while evaluating conditional breakpoint """
1051 def __init__(self, thread_id, exc_type, stacktrace):
1052 self.sequence = 0
1053 self.thread_id = thread_id
1054 self.stacktrace = stacktrace
1055 self.exc_type = exc_type
1056
1057 def doIt(self, dbg):
1058 try:
1059 callstack = "<xml>"
1060
1061 makeValid = pydevd_vars.makeValidXmlValue
1062
1063 for filename, line, methodname, methodobj in self.stacktrace:
1064 if file_system_encoding.lower() != "utf-8" and hasattr(filename, "decode"):
1065 # filename is a byte string encoded using the file system encoding
1066 # convert it to utf8
1067 filename = filename.decode(file_system_encoding).encode("utf-8")
1068
1069 callstack += '<frame thread_id = "%s" file="%s" line="%s" name="%s" obj="%s" />' \
1070 % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj))
1071 callstack += "</xml>"
1072
1073 cmd = dbg.cmdFactory.makeSendBreakpointExceptionMessage(self.sequence, self.exc_type + "\t" + callstack)
1074 dbg.writer.addCommand(cmd)
1075 except:
1076 exc = GetExceptionTracebackStr()
1077 sys.stderr.write('%s\n' % (exc,))
1078 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Exception: " + exc)
1079 dbg.writer.addCommand(cmd)
1080
1081
1082#=======================================================================================================================
1083# InternalSendCurrExceptionTrace
1084#=======================================================================================================================
1085class InternalSendCurrExceptionTrace(InternalThreadCommand):
1086 """ Send details of the exception that was caught and where we've broken in.
1087 """
1088 def __init__(self, thread_id, arg, curr_frame_id):
1089 '''
1090 :param arg: exception type, description, traceback object
1091 '''
1092 self.sequence = 0
1093 self.thread_id = thread_id
1094 self.curr_frame_id = curr_frame_id
1095 self.arg = arg
1096
1097 def doIt(self, dbg):
1098 try:
1099 cmd = dbg.cmdFactory.makeSendCurrExceptionTraceMessage(self.sequence, self.thread_id, self.curr_frame_id, *self.arg)
1100 del self.arg
1101 dbg.writer.addCommand(cmd)
1102 except:
1103 exc = GetExceptionTracebackStr()
1104 sys.stderr.write('%s\n' % (exc,))
1105 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace: " + exc)
1106 dbg.writer.addCommand(cmd)
1107
1108#=======================================================================================================================
1109# InternalSendCurrExceptionTraceProceeded
1110#=======================================================================================================================
1111class InternalSendCurrExceptionTraceProceeded(InternalThreadCommand):
1112 """ Send details of the exception that was caught and where we've broken in.
1113 """
1114 def __init__(self, thread_id):
1115 self.sequence = 0
1116 self.thread_id = thread_id
1117
1118 def doIt(self, dbg):
1119 try:
1120 cmd = dbg.cmdFactory.makeSendCurrExceptionTraceProceededMessage(self.sequence, self.thread_id)
1121 dbg.writer.addCommand(cmd)
1122 except:
1123 exc = GetExceptionTracebackStr()
1124 sys.stderr.write('%s\n' % (exc,))
1125 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc)
1126 dbg.writer.addCommand(cmd)
1127
1128
1129#=======================================================================================================================
1130# InternalEvaluateConsoleExpression
1131#=======================================================================================================================
1132class InternalEvaluateConsoleExpression(InternalThreadCommand):
1133 """ Execute the given command in the debug console """
1134
1135 def __init__(self, seq, thread_id, frame_id, line):
1136 self.sequence = seq
1137 self.thread_id = thread_id
1138 self.frame_id = frame_id
1139 self.line = line
1140
1141 def doIt(self, dbg):
1142 """ Create an XML for console output, error and more (true/false)
1143 <xml>
1144 <output message=output_message></output>
1145 <error message=error_message></error>
1146 <more>true/false</more>
1147 </xml>
1148 """
1149 try:
1150 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1151 if frame is not None:
1152 console_message = pydevd_console.execute_console_command(frame, self.thread_id, self.frame_id, self.line)
1153 cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, console_message.toXML())
1154 else:
1155 from pydevd_console import ConsoleMessage
1156 console_message = ConsoleMessage()
1157 console_message.add_console_message(
1158 pydevd_console.CONSOLE_ERROR,
1159 "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id),
1160 )
1161 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, console_message.toXML())
1162 except:
1163 exc = GetExceptionTracebackStr()
1164 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
1165 dbg.writer.addCommand(cmd)
1166
1167
1168#=======================================================================================================================
1169# InternalRunCustomOperation
1170#=======================================================================================================================
1171class InternalRunCustomOperation(InternalThreadCommand):
1172 """ Run a custom command on an expression
1173 """
1174 def __init__(self, seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname):
1175 self.sequence = seq
1176 self.thread_id = thread_id
1177 self.frame_id = frame_id
1178 self.scope = scope
1179 self.attrs = attrs
1180 self.style = style
1181 self.code_or_file = unquote_plus(encoded_code_or_file)
1182 self.fnname = fnname
1183
1184 def doIt(self, dbg):
1185 try:
1186 res = pydevd_vars.customOperation(self.thread_id, self.frame_id, self.scope, self.attrs,
1187 self.style, self.code_or_file, self.fnname)
1188 resEncoded = quote_plus(res)
1189 cmd = dbg.cmdFactory.makeCustomOperationMessage(self.sequence, resEncoded)
1190 dbg.writer.addCommand(cmd)
1191 except:
1192 exc = GetExceptionTracebackStr()
1193 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in running custom operation" + exc)
1194 dbg.writer.addCommand(cmd)
1195
1196
1197#=======================================================================================================================
1198# InternalConsoleGetCompletions
1199#=======================================================================================================================
1200class InternalConsoleGetCompletions(InternalThreadCommand):
1201 """ Fetch the completions in the debug console
1202 """
1203 def __init__(self, seq, thread_id, frame_id, act_tok):
1204 self.sequence = seq
1205 self.thread_id = thread_id
1206 self.frame_id = frame_id
1207 self.act_tok = act_tok
1208
1209 def doIt(self, dbg):
1210 """ Get completions and write back to the client
1211 """
1212 try:
1213 frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
1214 completions_xml = pydevd_console.get_completions(frame, self.act_tok)
1215 cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, completions_xml)
1216 dbg.writer.addCommand(cmd)
1217 except:
1218 exc = GetExceptionTracebackStr()
1219 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in fetching completions" + exc)
1220 dbg.writer.addCommand(cmd)
1221
Tor Norbyec667c1f2014-05-28 17:06:51 -07001222
1223#=======================================================================================================================
Tor Norbye3a2425a2013-11-04 10:16:08 -08001224# InternalConsoleExec
1225#=======================================================================================================================
1226class InternalConsoleExec(InternalThreadCommand):
1227 """ gets the value of a variable """
1228
1229 def __init__(self, seq, thread_id, frame_id, expression):
1230 self.sequence = seq
1231 self.thread_id = thread_id
1232 self.frame_id = frame_id
1233 self.expression = expression
1234
1235 def doIt(self, dbg):
1236 """ Converts request into python variable """
Tor Norbye3a2425a2013-11-04 10:16:08 -08001237 try:
1238 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001239 #don't trace new threads created by console command
1240 disable_trace_thread_modules()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001241
1242 result = pydevconsole.consoleExec(self.thread_id, self.frame_id, self.expression)
1243 xml = "<xml>"
1244 xml += pydevd_vars.varToXML(result, "")
1245 xml += "</xml>"
1246 cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
1247 dbg.writer.addCommand(cmd)
1248 except:
1249 exc = GetExceptionTracebackStr()
1250 sys.stderr.write('%s\n' % (exc,))
1251 cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating console expression " + exc)
1252 dbg.writer.addCommand(cmd)
1253 finally:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001254 enable_trace_thread_modules()
1255
Tor Norbye3a2425a2013-11-04 10:16:08 -08001256 sys.stderr.flush()
1257 sys.stdout.flush()
1258
Tor Norbye3a2425a2013-11-04 10:16:08 -08001259
1260#=======================================================================================================================
1261# PydevdFindThreadById
1262#=======================================================================================================================
1263def PydevdFindThreadById(thread_id):
1264 try:
1265 # there was a deadlock here when I did not remove the tracing function when thread was dead
1266 threads = threading.enumerate()
1267 for i in threads:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001268 tid = GetThreadId(i)
1269 if thread_id == tid or thread_id.endswith('|' + tid):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001270 return i
1271
1272 sys.stderr.write("Could not find thread %s\n" % thread_id)
1273 sys.stderr.write("Available: %s\n" % [GetThreadId(t) for t in threads])
1274 sys.stderr.flush()
1275 except:
1276 traceback.print_exc()
1277
1278 return None
1279