Coverage for C:\Program Files\JetBrains\PyCharm Community Edition 2020.3.2\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_comm.py : 2%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1''' pydevd - a debugging daemon
2This is the daemon you launch for python remote debugging.
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
16 Commands:
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
29 106 CMD_THREAD_RUN JAVA id resume the thread
30 PYDB id \t reason notifies JAVA that thread was resumed
32 107 STEP_INTO JAVA thread_id
33 108 STEP_OVER JAVA thread_id
34 109 STEP_RETURN JAVA thread_id
36 110 GET_VARIABLE JAVA thread_id \t frame_id \t GET_VARIABLE with XML of var content
37 FRAME|GLOBAL \t attributes*
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
50 200 CMD_REDIRECT_OUTPUT JAVA streams to redirect as string -
51 'STDOUT' (redirect only STDOUT)
52 'STDERR' (redirect only STDERR)
53 'STDOUT STDERR' (redirect both streams)
55500 series diagnostics/ok
56 501 VERSION either Version string (1.0) Currently just used at startup
57 502 RETURN either Depends on caller -
59900 series: errors
60 901 ERROR either - This is reserved for unexpected errors.
62 * JAVA - remote debugger, the java end
63 * PYDB - pydevd, the python end
64'''
66import itertools
68from _pydev_bundle.pydev_imports import _queue
69from _pydev_imps._pydev_saved_modules import thread
70from _pydev_imps._pydev_saved_modules import threading
71from _pydev_imps._pydev_saved_modules import time
72from _pydev_imps._pydev_saved_modules import socket
73from socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR, SOL_SOCKET, SO_REUSEADDR, SHUT_RDWR, timeout
74from _pydevd_bundle.pydevd_constants import DebugInfoHolder, get_thread_id, IS_JYTHON, IS_PY2, IS_PY3K, \
75 IS_PY36_OR_GREATER, STATE_RUN, dict_keys, ASYNC_EVAL_TIMEOUT_SEC, IS_IRONPYTHON, GlobalDebuggerHolder, \
76 get_global_debugger, GetGlobalDebugger, set_global_debugger # Keep for backward compatibility @UnusedImport
77from _pydev_bundle.pydev_override import overrides
78import json
79import weakref
81try:
82 from urllib import quote_plus, unquote, unquote_plus
83except:
84 from urllib.parse import quote_plus, unquote, unquote_plus #@Reimport @UnresolvedImport
86if IS_IRONPYTHON:
87 # redefine `unquote` for IronPython, since we use it only for logging messages, but it leads to SOF with IronPython
88 def unquote(s):
89 return s
91from _pydevd_bundle import pydevd_console_integration
92from _pydevd_bundle import pydevd_vars
93import pydevd_tracing
94from _pydevd_bundle import pydevd_xml
95from _pydevd_bundle import pydevd_vm_type
96from _pydevd_bundle import pydevd_bytecode_utils
97from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, norm_file_to_client, is_real_file
98import pydevd_file_utils
99import os
100import sys
101import inspect
102import traceback
103from _pydevd_bundle.pydevd_utils import quote_smart as quote, compare_object_attrs_key, to_string, \
104 get_non_pydevd_threads, is_pandas_container, is_numpy_container
105from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
106from _pydev_bundle import pydev_log
107from _pydev_bundle import _pydev_completer
109from pydevd_tracing import get_exception_traceback_str
110from _pydevd_bundle import pydevd_console
111from _pydev_bundle.pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules
113try:
114 import cStringIO as StringIO #may not always be available @UnusedImport
115except:
116 try:
117 import StringIO #@Reimport
118 except:
119 import io as StringIO
121from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE
122get_file_type = DONT_TRACE.get
125# CMD_XXX constants imported for backward compatibility
126from _pydevd_bundle.pydevd_comm_constants import (
127 ID_TO_MEANING, CMD_RUN, CMD_LIST_THREADS, CMD_THREAD_CREATE, CMD_THREAD_KILL,
128 CMD_THREAD_SUSPEND, CMD_THREAD_RUN, CMD_STEP_INTO, CMD_STEP_OVER, CMD_STEP_RETURN, CMD_GET_VARIABLE,
129 CMD_SET_BREAK, CMD_REMOVE_BREAK, CMD_EVALUATE_EXPRESSION, CMD_GET_FRAME,
130 CMD_EXEC_EXPRESSION, CMD_WRITE_TO_CONSOLE, CMD_CHANGE_VARIABLE, CMD_RUN_TO_LINE,
131 CMD_RELOAD_CODE, CMD_GET_COMPLETIONS, CMD_CONSOLE_EXEC, CMD_ADD_EXCEPTION_BREAK,
132 CMD_REMOVE_EXCEPTION_BREAK, CMD_LOAD_SOURCE, CMD_ADD_DJANGO_EXCEPTION_BREAK,
133 CMD_REMOVE_DJANGO_EXCEPTION_BREAK, CMD_SET_NEXT_STATEMENT, CMD_SMART_STEP_INTO,
134 CMD_EXIT, CMD_SIGNATURE_CALL_TRACE, CMD_SET_PY_EXCEPTION, CMD_GET_FILE_CONTENTS,
135 CMD_SET_PROPERTY_TRACE, CMD_EVALUATE_CONSOLE_EXPRESSION, CMD_RUN_CUSTOM_OPERATION,
136 CMD_GET_BREAKPOINT_EXCEPTION, CMD_STEP_CAUGHT_EXCEPTION, CMD_SEND_CURR_EXCEPTION_TRACE,
137 CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE,
138 CMD_SHOW_CONSOLE, CMD_GET_ARRAY, CMD_STEP_INTO_MY_CODE, CMD_GET_CONCURRENCY_EVENT,
139 CMD_SHOW_RETURN_VALUES, CMD_SET_UNIT_TEST_DEBUGGING_MODE, CMD_INPUT_REQUESTED, CMD_GET_DESCRIPTION, CMD_PROCESS_CREATED,
140 CMD_SHOW_CYTHON_WARNING, CMD_LOAD_FULL_VALUE, CMD_GET_THREAD_STACK, CMD_THREAD_DUMP_TO_STDERR,
141 CMD_STOP_ON_START, CMD_GET_EXCEPTION_DETAILS, CMD_PROCESS_CREATED_MSG_RECEIVED, CMD_PYDEVD_JSON_CONFIG,
142 CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, CMD_THREAD_RESUME_SINGLE_NOTIFICATION,
143 CMD_REDIRECT_OUTPUT, CMD_GET_NEXT_STATEMENT_TARGETS, CMD_SET_PROJECT_ROOTS, CMD_VERSION,
144 CMD_RETURN, CMD_SET_PROTOCOL, CMD_ERROR, CMD_GET_SMART_STEP_INTO_VARIANTS, CMD_DATAVIEWER_ACTION,)
145MAX_IO_MSG_SIZE = 1000 #if the io is too big, we'll not send all (could make the debugger too non-responsive)
146#this number can be changed if there's need to do so
148VERSION_STRING = "@@BUILD_NUMBER@@"
150from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding
151file_system_encoding = getfilesystemencoding()
152filesystem_encoding_is_utf8 = file_system_encoding.lower() in ('utf-8', 'utf_8', 'utf8')
155class CommunicationRole(object):
156 """The class that contains the constants of roles that `PyDB` can play in
157 the communication with the IDE.
158 """
159 CLIENT = 0
160 SERVER = 1
163#--------------------------------------------------------------------------------------------------- UTILITIES
165#=======================================================================================================================
166# pydevd_log
167#=======================================================================================================================
168def pydevd_log(level, *args):
169 """ levels are:
170 0 most serious warnings/errors
171 1 warnings/significant events
172 2 informational trace
173 """
174 if level <= DebugInfoHolder.DEBUG_TRACE_LEVEL:
175 #yes, we can have errors printing if the console of the program has been finished (and we're still trying to print something)
176 try:
177 sys.stderr.write('%s\n' % (args,))
178 except:
179 pass
182#------------------------------------------------------------------- ACTUAL COMM
184#=======================================================================================================================
185# PyDBDaemonThread
186#=======================================================================================================================
187class PyDBDaemonThread(threading.Thread):
188 created_pydb_daemon_threads = {}
190 def __init__(self, target_and_args=None):
191 '''
192 :param target_and_args:
193 tuple(func, args, kwargs) if this should be a function and args to run.
194 -- Note: use through run_as_pydevd_daemon_thread().
195 '''
196 threading.Thread.__init__(self)
197 self.killReceived = False
198 mark_as_pydevd_daemon_thread(self)
199 self._target_and_args = target_and_args
201 def run(self):
202 created_pydb_daemon = self.created_pydb_daemon_threads
203 created_pydb_daemon[self] = 1
204 try:
205 try:
206 if IS_JYTHON and not isinstance(threading.currentThread(), threading._MainThread):
207 # we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading'
208 # module, and the new instance of main thread is created
209 import org.python.core as PyCore #@UnresolvedImport
210 ss = PyCore.PySystemState()
211 # Note: Py.setSystemState() affects only the current thread.
212 PyCore.Py.setSystemState(ss)
214 self._stop_trace()
215 self._warn_pydevd_thread_is_traced()
216 self._on_run()
217 except:
218 if sys is not None and traceback is not None:
219 traceback.print_exc()
220 finally:
221 del created_pydb_daemon[self]
223 def _on_run(self):
224 if self._target_and_args is not None:
225 target, args, kwargs = self._target_and_args
226 target(*args, **kwargs)
227 else:
228 raise NotImplementedError('Should be reimplemented by: %s' % self.__class__)
230 def do_kill_pydev_thread(self):
231 self.killReceived = True
233 def _stop_trace(self):
234 if self.pydev_do_not_trace:
235 pydevd_tracing.SetTrace(None) # no debugging on this thread
237 def _warn_pydevd_thread_is_traced(self):
238 if self.pydev_do_not_trace and sys.gettrace():
239 pydevd_log(1, "The debugger thread '%s' is traced which may lead to debugging performance issues." % self.__class__.__name__)
242def mark_as_pydevd_daemon_thread(thread):
243 thread.pydev_do_not_trace = True
244 thread.is_pydev_daemon_thread = True
245 thread.daemon = True
248def run_as_pydevd_daemon_thread(func, *args, **kwargs):
249 '''
250 Runs a function as a pydevd daemon thread (without any tracing in place).
251 '''
252 t = PyDBDaemonThread(target_and_args=(func, args, kwargs))
253 t.name = '%s (pydevd daemon thread)' % (func.__name__,)
254 t.start()
255 return t
258#=======================================================================================================================
259# ReaderThread
260#=======================================================================================================================
261class ReaderThread(PyDBDaemonThread):
262 """ reader thread reads and dispatches commands in an infinite loop """
264 def __init__(self, sock):
265 PyDBDaemonThread.__init__(self)
266 self.sock = sock
267 self.setName("pydevd.Reader")
268 from _pydevd_bundle.pydevd_process_net_command import process_net_command
269 self.process_net_command = process_net_command
270 self.global_debugger_holder = GlobalDebuggerHolder
274 def do_kill_pydev_thread(self):
275 #We must close the socket so that it doesn't stay halted there.
276 self.killReceived = True
277 try:
278 self.sock.shutdown(SHUT_RD) #shutdown the socket for read
279 except:
280 #just ignore that
281 pass
283 @overrides(PyDBDaemonThread._on_run)
284 def _on_run(self):
285 read_buffer = ""
286 try:
288 while not self.killReceived:
289 try:
290 r = self.sock.recv(1024)
291 except:
292 if not self.killReceived:
293 traceback.print_exc()
294 self.handle_except()
295 return #Finished communication.
297 #Note: the java backend is always expected to pass utf-8 encoded strings. We now work with unicode
298 #internally and thus, we may need to convert to the actual encoding where needed (i.e.: filenames
299 #on python 2 may need to be converted to the filesystem encoding).
300 if hasattr(r, 'decode'):
301 r = r.decode('utf-8')
303 read_buffer += r
304 if DebugInfoHolder.DEBUG_RECORD_SOCKET_READS:
305 sys.stderr.write(u'debugger: received >>%s<<\n' % (read_buffer,))
306 sys.stderr.flush()
308 if len(read_buffer) == 0:
309 self.handle_except()
310 break
311 while read_buffer.find(u'\n') != -1:
312 command, read_buffer = read_buffer.split(u'\n', 1)
314 args = command.split(u'\t', 2)
315 try:
316 cmd_id = int(args[0])
317 pydev_log.debug('Received command: %s %s\n' % (ID_TO_MEANING.get(str(cmd_id), '???'), command,))
318 self.process_command(cmd_id, int(args[1]), args[2])
319 except:
320 traceback.print_exc()
321 sys.stderr.write("Can't process net command: %s\n" % command)
322 sys.stderr.flush()
324 except:
325 traceback.print_exc()
326 self.handle_except()
329 def handle_except(self):
330 self.global_debugger_holder.global_dbg.finish_debugging_session()
332 def process_command(self, cmd_id, seq, text):
333 self.process_net_command(self.global_debugger_holder.global_dbg, cmd_id, seq, text)
336#----------------------------------------------------------------------------------- SOCKET UTILITIES - WRITER
337#=======================================================================================================================
338# WriterThread
339#=======================================================================================================================
340class WriterThread(PyDBDaemonThread):
341 """ writer thread writes out the commands in an infinite loop """
342 def __init__(self, sock):
343 PyDBDaemonThread.__init__(self)
344 self.sock = sock
345 self.setName("pydevd.Writer")
346 self.cmdQueue = _queue.Queue()
347 if pydevd_vm_type.get_vm_type() == 'python':
348 self.timeout = 0
349 else:
350 self.timeout = 0.1
352 def add_command(self, cmd):
353 """ cmd is NetCommand """
354 if not self.killReceived: #we don't take new data after everybody die
355 self.cmdQueue.put(cmd)
357 @overrides(PyDBDaemonThread._on_run)
358 def _on_run(self):
359 """ just loop and write responses """
361 try:
362 while True:
363 try:
364 try:
365 cmd = self.cmdQueue.get(1, 0.1)
366 except _queue.Empty:
367 if self.killReceived:
368 try:
369 self.sock.shutdown(SHUT_WR)
370 self.sock.close()
371 except:
372 pass
374 return #break if queue is empty and killReceived
375 else:
376 continue
377 except:
378 #pydevd_log(0, 'Finishing debug communication...(1)')
379 #when liberating the thread here, we could have errors because we were shutting down
380 #but the thread was still not liberated
381 return
382 cmd.send(self.sock)
384 if cmd.id == CMD_EXIT:
385 break
386 if time is None:
387 break #interpreter shutdown
388 time.sleep(self.timeout)
389 except Exception:
390 GlobalDebuggerHolder.global_dbg.finish_debugging_session()
391 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 0:
392 traceback.print_exc()
394 def empty(self):
395 return self.cmdQueue.empty()
399#--------------------------------------------------- CREATING THE SOCKET THREADS
401#=======================================================================================================================
402# start_server
403#=======================================================================================================================
404def start_server(port):
405 """ binds to a port, waits for the debugger to connect """
406 s = socket(AF_INET, SOCK_STREAM)
407 s.settimeout(None)
409 try:
410 from socket import SO_REUSEPORT
411 s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
412 except ImportError:
413 s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
415 s.bind(('', port))
416 pydevd_log(1, "Bound to port ", str(port))
418 try:
419 s.listen(1)
420 newSock, _addr = s.accept()
421 pydevd_log(1, "Connection accepted")
422 # closing server socket is not necessary but we don't need it
423 s.shutdown(SHUT_RDWR)
424 s.close()
425 return newSock
427 except:
428 sys.stderr.write("Could not bind to port: %s\n" % (port,))
429 sys.stderr.flush()
430 traceback.print_exc()
432#=======================================================================================================================
433# start_client
434#=======================================================================================================================
435def start_client(host, port):
436 """ connects to a host/port """
437 pydevd_log(1, "Connecting to ", host, ":", str(port))
439 s = socket(AF_INET, SOCK_STREAM)
441 # Set TCP keepalive on an open socket.
442 # It activates after 1 second (TCP_KEEPIDLE,) of idleness,
443 # then sends a keepalive ping once every 3 seconds (TCP_KEEPINTVL),
444 # and closes the connection after 5 failed ping (TCP_KEEPCNT), or 15 seconds
445 try:
446 from socket import IPPROTO_TCP, SO_KEEPALIVE, TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT
447 s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1)
448 s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 1)
449 s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 3)
450 s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 5)
451 except ImportError:
452 pass # May not be available everywhere.
454 try:
455 s.settimeout(10) # 10 seconds timeout
456 s.connect((host, port))
457 s.settimeout(None) # no timeout after connected
458 pydevd_log(1, "Connected.")
459 return s
460 except:
461 sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
462 sys.stderr.flush()
463 traceback.print_exc()
464 raise
469#------------------------------------------------------------------------------------ MANY COMMUNICATION STUFF
471#=======================================================================================================================
472# NetCommand
473#=======================================================================================================================
474class NetCommand:
475 """ Commands received/sent over the network.
477 Command can represent command received from the debugger,
478 or one to be sent by daemon.
479 """
480 next_seq = 0 # sequence numbers
482 # Protocol where each line is a new message (text is quoted to prevent new lines).
483 QUOTED_LINE_PROTOCOL = 'quoted-line'
485 # Uses http protocol to provide a new message.
486 # i.e.: Content-Length:xxx\r\n\r\npayload
487 HTTP_PROTOCOL = 'http'
489 protocol = QUOTED_LINE_PROTOCOL
491 _showing_debug_info = 0
492 _show_debug_info_lock = threading.RLock()
494 def __init__(self, cmd_id, seq, text):
495 """
496 If sequence is 0, new sequence will be generated (otherwise, this was the response
497 to a command from the client).
498 """
499 self.id = cmd_id
500 if seq == 0:
501 NetCommand.next_seq += 2
502 seq = NetCommand.next_seq
503 self.seq = seq
505 if IS_PY2:
506 if isinstance(text, unicode):
507 text = text.encode('utf-8')
508 else:
509 assert isinstance(text, str)
510 else:
511 assert isinstance(text, str)
513 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
514 self._show_debug_info(cmd_id, seq, text)
516 if self.protocol == self.HTTP_PROTOCOL:
517 msg = '%s\t%s\t%s\n' % (cmd_id, seq, text)
518 else:
519 encoded = quote(to_string(text), '/<>_=" \t')
520 msg = '%s\t%s\t%s\n' % (cmd_id, seq, encoded)
523 if IS_PY2:
524 assert isinstance(msg, str) # i.e.: bytes
525 as_bytes = msg
526 else:
527 if isinstance(msg, str):
528 msg = msg.encode('utf-8')
530 assert isinstance(msg, bytes)
531 as_bytes = msg
532 self._as_bytes = as_bytes
534 def send(self, sock):
535 as_bytes = self._as_bytes
536 if self.protocol == self.HTTP_PROTOCOL:
537 sock.sendall(('Content-Length: %s\r\n\r\n' % len(as_bytes)).encode('ascii'))
539 sock.sendall(as_bytes)
541 @classmethod
542 def _show_debug_info(cls, cmd_id, seq, text):
543 with cls._show_debug_info_lock:
544 # Only one thread each time (rlock).
545 if cls._showing_debug_info:
546 # avoid recursing in the same thread (just printing could create
547 # a new command when redirecting output).
548 return
550 cls._showing_debug_info += 1
551 try:
552 out_message = 'sending cmd --> '
553 out_message += "%20s" % ID_TO_MEANING.get(str(cmd_id), 'UNKNOWN')
554 out_message += ' '
555 out_message += text.replace('\n', ' ')
556 try:
557 sys.stderr.write('%s\n' % (out_message,))
558 except:
559 pass
560 finally:
561 cls._showing_debug_info -= 1
564#=======================================================================================================================
565# NetCommandFactory
566#=======================================================================================================================
567class NetCommandFactory:
569 def _thread_to_xml(self, thread):
570 """ thread information as XML """
571 name = pydevd_xml.make_valid_xml_value(thread.getName())
572 cmdText = '<thread name="%s" id="%s" />' % (quote(name), get_thread_id(thread))
573 return cmdText
575 def make_error_message(self, seq, text):
576 cmd = NetCommand(CMD_ERROR, seq, text)
577 if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2:
578 sys.stderr.write("Error: %s" % (text,))
579 return cmd
581 def make_protocol_set_message(self, seq):
582 return NetCommand(CMD_SET_PROTOCOL, seq, '')
584 def make_thread_created_message(self, thread):
585 cmdText = "<xml>" + self._thread_to_xml(thread) + "</xml>"
586 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
588 def make_process_created_message(self):
589 cmdText = '<process/>'
590 return NetCommand(CMD_PROCESS_CREATED, 0, cmdText)
592 def make_show_warning_message(self, message_id):
593 try:
594 cmdText = '<xml><warning id="%s" /></xml>' % message_id
595 return NetCommand(CMD_SHOW_CYTHON_WARNING, 0, cmdText)
596 except:
597 return self.make_error_message(0, get_exception_traceback_str())
599 def make_custom_frame_created_message(self, frameId, frameDescription):
600 frameDescription = pydevd_xml.make_valid_xml_value(frameDescription)
601 cmdText = '<xml><thread name="%s" id="%s"/></xml>' % (frameDescription, frameId)
602 return NetCommand(CMD_THREAD_CREATE, 0, cmdText)
605 def make_list_threads_message(self, seq):
606 """ returns thread listing as XML """
607 try:
608 threads = get_non_pydevd_threads()
609 cmd_text = ["<xml>"]
610 append = cmd_text.append
611 for thread in threads:
612 if is_thread_alive(thread):
613 append(self._thread_to_xml(thread))
614 append("</xml>")
615 return NetCommand(CMD_RETURN, seq, ''.join(cmd_text))
616 except:
617 return self.make_error_message(seq, get_exception_traceback_str())
619 def make_get_thread_stack_message(self, seq, thread_id, topmost_frame, must_be_suspended=False):
620 """
621 Returns thread stack as XML.
623 :param be_suspended: If True and the thread is not suspended, returns None.
624 """
625 try:
626 # If frame is None, the return is an empty frame list.
627 cmd_text = ['<xml><thread id="%s">' % (thread_id,)]
629 if topmost_frame is not None:
630 try:
631 # Note: if we detect that we're already stopped in a given place within
632 # the debugger, use that stack instead of creating a new one with the
633 # current position (this is needed because when an uncaught exception
634 # is reported for a given frame we are actually stopped in a different
635 # place within the debugger).
636 frame = topmost_frame
637 thread_stack_str = ''
638 while frame is not None:
639 if frame.f_code.co_name == 'do_wait_suspend' and frame.f_code.co_filename.endswith('pydevd.py'):
640 thread_stack_str = frame.f_locals.get('thread_stack_str')
641 break
642 frame = frame.f_back
643 else:
644 # Could not find stack of suspended frame...
645 if must_be_suspended:
646 return None
647 cmd_text.append(thread_stack_str or self.make_thread_stack_str(topmost_frame))
648 finally:
649 topmost_frame = None
650 cmd_text.append('</thread></xml>')
651 return NetCommand(CMD_GET_THREAD_STACK, seq, ''.join(cmd_text))
652 except:
653 return self.make_error_message(seq, get_exception_traceback_str())
655 def make_variable_changed_message(self, seq, payload):
656 # notify debugger that value was changed successfully
657 return NetCommand(CMD_RETURN, seq, payload)
659 def make_io_message(self, v, ctx):
660 '''
661 @param v: the message to pass to the debug server
662 @param ctx: 1 for stdio 2 for stderr
663 '''
665 try:
666 if len(v) > MAX_IO_MSG_SIZE:
667 v = v[0:MAX_IO_MSG_SIZE]
668 v += '...'
670 v = pydevd_xml.make_valid_xml_value(quote(v, '/>_= '))
671 return NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '<xml><io s="%s" ctx="%s"/></xml>' % (v, ctx))
672 except:
673 return self.make_error_message(0, get_exception_traceback_str())
675 def make_version_message(self, seq):
676 try:
677 return NetCommand(CMD_VERSION, seq, VERSION_STRING)
678 except:
679 return self.make_error_message(seq, get_exception_traceback_str())
681 def make_thread_killed_message(self, id):
682 try:
683 return NetCommand(CMD_THREAD_KILL, 0, str(id))
684 except:
685 return self.make_error_message(0, get_exception_traceback_str())
687 def make_thread_stack_str(self, frame, frame_to_lineno=None):
688 '''
689 :param frame_to_lineno:
690 If available, the line number for the frame will be gotten from this dict,
691 otherwise frame.f_lineno will be used (needed for unhandled exceptions as
692 the place where we report may be different from the place where it's raised).
693 '''
694 if frame_to_lineno is None:
695 frame_to_lineno = {}
696 make_valid_xml_value = pydevd_xml.make_valid_xml_value
697 cmd_text_list = []
698 append = cmd_text_list.append
700 curr_frame = frame
701 frame = None # Clear frame reference
702 try:
703 while curr_frame:
704 my_id = id(curr_frame)
706 if curr_frame.f_code is None:
707 break # Iron Python sometimes does not have it!
709 method_name = curr_frame.f_code.co_name # method name (if in method) or ? if global
710 if method_name is None:
711 break # Iron Python sometimes does not have it!
713 abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(curr_frame)
714 if get_file_type(abs_path_real_path_and_base[2]) == PYDEV_FILE:
715 # Syntax errors are a special case in which we don't want to skip the debugger files.
716 # When a syntax error happens, we stop either in the `execfile` or `_exec` function.
717 exception_info, is_syntax_error = curr_frame.f_locals.get('__exception__'), False
718 if exception_info:
719 is_syntax_error = exception_info[0] is SyntaxError
720 if not is_syntax_error:
721 # Skip pydevd files.
722 curr_frame = curr_frame.f_back
723 continue
725 my_file = abs_path_real_path_and_base[0]
727 if is_real_file(my_file):
728 # if filename is Jupyter cell id
729 my_file = pydevd_file_utils.norm_file_to_client(abs_path_real_path_and_base[0])
731 if file_system_encoding.lower() != "utf-8" and hasattr(my_file, "decode"):
732 # my_file is a byte string encoded using the file system encoding
733 # convert it to utf8
734 my_file = my_file.decode(file_system_encoding).encode("utf-8")
736 #print "file is ", my_file
737 #my_file = inspect.getsourcefile(curr_frame) or inspect.getfile(frame)
739 lineno = frame_to_lineno.get(curr_frame, curr_frame.f_lineno)
740 # print("line is ", lineno)
742 # Note: variables are all gotten 'on-demand'.
743 append('<frame id="%s" name="%s" ' % (my_id , make_valid_xml_value(method_name)))
744 append('file="%s" line="%s">' % (make_valid_xml_value(my_file), lineno))
745 append("</frame>")
746 curr_frame = curr_frame.f_back
747 except:
748 traceback.print_exc()
750 curr_frame = None # Clear frame reference
751 return ''.join(cmd_text_list)
753 def make_thread_suspend_str(
754 self,
755 thread_id,
756 frame,
757 stop_reason=None,
758 message=None,
759 suspend_type="trace",
760 frame_to_lineno=None
761 ):
762 """
763 :return tuple(str,str):
764 Returns tuple(thread_suspended_str, thread_stack_str).
766 i.e.:
767 (
768 '''
769 <xml>
770 <thread id="id" stop_reason="reason">
771 <frame id="id" name="functionName " file="file" line="line">
772 </frame>
773 </thread>
774 </xml>
775 '''
776 ,
777 '''
778 <frame id="id" name="functionName " file="file" line="line">
779 </frame>
780 '''
781 )
782 """
783 make_valid_xml_value = pydevd_xml.make_valid_xml_value
784 cmd_text_list = []
785 append = cmd_text_list.append
787 cmd_text_list.append('<xml>')
788 if message:
789 message = make_valid_xml_value(message)
791 append('<thread id="%s"' % (thread_id,))
792 if stop_reason is not None:
793 append(' stop_reason="%s"' % (stop_reason,))
794 if message is not None:
795 append(' message="%s"' % (message,))
796 if suspend_type is not None:
797 append(' suspend_type="%s"' % (suspend_type,))
798 append('>')
799 thread_stack_str = self.make_thread_stack_str(frame, frame_to_lineno)
800 append(thread_stack_str)
801 append("</thread></xml>")
803 return ''.join(cmd_text_list), thread_stack_str
805 def make_thread_suspend_message(self, thread_id, frame, stop_reason, message, suspend_type, frame_to_lineno=None):
806 try:
807 thread_suspend_str, thread_stack_str = self.make_thread_suspend_str(
808 thread_id, frame, stop_reason, message, suspend_type, frame_to_lineno=frame_to_lineno)
809 cmd = NetCommand(CMD_THREAD_SUSPEND, 0, thread_suspend_str)
810 cmd.thread_stack_str = thread_stack_str
811 cmd.thread_suspend_str = thread_suspend_str
812 return cmd
813 except:
814 return self.make_error_message(0, get_exception_traceback_str())
816 def make_thread_suspend_single_notification(self, thread_id, stop_reason):
817 try:
818 return NetCommand(CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, 0, json.dumps(
819 {'thread_id': thread_id, 'stop_reason': stop_reason}))
820 except:
821 return self.make_error_message(0, get_exception_traceback_str())
823 def make_thread_resume_single_notification(self, thread_id):
824 try:
825 return NetCommand(CMD_THREAD_RESUME_SINGLE_NOTIFICATION, 0, json.dumps(
826 {'thread_id': thread_id}))
827 except:
828 return self.make_error_message(0, get_exception_traceback_str())
830 def make_thread_run_message(self, thread_id, reason):
831 try:
832 return NetCommand(CMD_THREAD_RUN, 0, "%s\t%s" % (thread_id, reason))
833 except:
834 return self.make_error_message(0, get_exception_traceback_str())
836 def make_get_variable_message(self, seq, payload):
837 try:
838 return NetCommand(CMD_GET_VARIABLE, seq, payload)
839 except Exception:
840 return self.make_error_message(seq, get_exception_traceback_str())
843 def make_get_array_message(self, seq, payload):
844 try:
845 return NetCommand(CMD_GET_ARRAY, seq, payload)
846 except Exception:
847 return self.make_error_message(seq, get_exception_traceback_str())
849 def make_successful_dataviewer_action_message(self, seq, payload):
850 try:
851 return NetCommand(CMD_DATAVIEWER_ACTION, seq, payload)
852 except Exception:
853 return self.make_error_message(seq, get_exception_traceback_str())
855 def make_get_description_message(self, seq, payload):
856 try:
857 return NetCommand(CMD_GET_DESCRIPTION, seq, payload)
858 except Exception:
859 return self.make_error_message(seq, get_exception_traceback_str())
861 def make_get_frame_message(self, seq, payload):
862 try:
863 return NetCommand(CMD_GET_FRAME, seq, payload)
864 except Exception:
865 return self.make_error_message(seq, get_exception_traceback_str())
868 def make_evaluate_expression_message(self, seq, payload):
869 try:
870 return NetCommand(CMD_EVALUATE_EXPRESSION, seq, payload)
871 except Exception:
872 return self.make_error_message(seq, get_exception_traceback_str())
874 def make_get_completions_message(self, seq, payload):
875 try:
876 return NetCommand(CMD_GET_COMPLETIONS, seq, payload)
877 except Exception:
878 return self.make_error_message(seq, get_exception_traceback_str())
880 def make_get_file_contents(self, seq, payload):
881 try:
882 return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload)
883 except Exception:
884 return self.make_error_message(seq, get_exception_traceback_str())
886 def make_send_breakpoint_exception_message(self, seq, payload):
887 try:
888 return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload)
889 except Exception:
890 return self.make_error_message(seq, get_exception_traceback_str())
892 def _make_send_curr_exception_trace_str(self, thread_id, exc_type, exc_desc, trace_obj):
893 while trace_obj.tb_next is not None:
894 trace_obj = trace_obj.tb_next
896 exc_type = pydevd_xml.make_valid_xml_value(str(exc_type)).replace('\t', ' ') or 'exception: type unknown'
897 exc_desc = pydevd_xml.make_valid_xml_value(str(exc_desc)).replace('\t', ' ') or 'exception: no description'
899 thread_suspend_str, thread_stack_str = self.make_thread_suspend_str(
900 thread_id, trace_obj.tb_frame, CMD_SEND_CURR_EXCEPTION_TRACE, '')
901 return exc_type, exc_desc, thread_suspend_str, thread_stack_str
903 def make_send_curr_exception_trace_message(self, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj):
904 try:
905 exc_type, exc_desc, thread_suspend_str, _thread_stack_str = self._make_send_curr_exception_trace_str(
906 thread_id, exc_type, exc_desc, trace_obj)
907 payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + thread_suspend_str
908 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload)
909 except Exception:
910 return self.make_error_message(seq, get_exception_traceback_str())
912 def make_get_exception_details_message(self, seq, thread_id, topmost_frame):
913 """Returns exception details as XML """
914 try:
915 # If the debugger is not suspended, just return the thread and its id.
916 cmd_text = ['<xml><thread id="%s" ' % (thread_id,)]
918 if topmost_frame is not None:
919 try:
920 frame = topmost_frame
921 topmost_frame = None
922 while frame is not None:
923 if frame.f_code.co_name == 'do_wait_suspend' and frame.f_code.co_filename.endswith('pydevd.py'):
924 arg = frame.f_locals.get('arg', None)
925 if arg is not None:
926 exc_type, exc_desc, _thread_suspend_str, thread_stack_str = self._make_send_curr_exception_trace_str(
927 thread_id, *arg)
928 cmd_text.append('exc_type="%s" ' % (exc_type,))
929 cmd_text.append('exc_desc="%s" ' % (exc_desc,))
930 cmd_text.append('>')
931 cmd_text.append(thread_stack_str)
932 break
933 frame = frame.f_back
934 else:
935 cmd_text.append('>')
936 finally:
937 frame = None
938 cmd_text.append('</thread></xml>')
939 return NetCommand(CMD_GET_EXCEPTION_DETAILS, seq, ''.join(cmd_text))
940 except:
941 return self.make_error_message(seq, get_exception_traceback_str())
943 def make_send_curr_exception_trace_proceeded_message(self, seq, thread_id):
944 try:
945 return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id))
946 except:
947 return self.make_error_message(0, get_exception_traceback_str())
949 def make_send_console_message(self, seq, payload):
950 try:
951 return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload)
952 except Exception:
953 return self.make_error_message(seq, get_exception_traceback_str())
955 def make_custom_operation_message(self, seq, payload):
956 try:
957 return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload)
958 except Exception:
959 return self.make_error_message(seq, get_exception_traceback_str())
961 def make_load_source_message(self, seq, source, dbg=None):
962 try:
963 net = NetCommand(CMD_LOAD_SOURCE, seq, '%s' % source)
965 except:
966 net = self.make_error_message(0, get_exception_traceback_str())
968 if dbg:
969 dbg.writer.add_command(net)
970 return net
972 def make_show_console_message(self, thread_id, frame):
973 try:
974 thread_suspended_str, _thread_stack_str = self.make_thread_suspend_str(thread_id, frame, CMD_SHOW_CONSOLE, '')
975 return NetCommand(CMD_SHOW_CONSOLE, 0, thread_suspended_str)
976 except:
977 return self.make_error_message(0, get_exception_traceback_str())
979 def make_input_requested_message(self, started):
980 try:
981 return NetCommand(CMD_INPUT_REQUESTED, 0, str(started))
982 except:
983 return self.make_error_message(0, get_exception_traceback_str())
985 def make_set_next_stmnt_status_message(self, seq, is_success, exception_msg):
986 try:
987 message = str(is_success) + '\t' + exception_msg
988 return NetCommand(CMD_SET_NEXT_STATEMENT, int(seq), message)
989 except:
990 return self.make_error_message(0, get_exception_traceback_str())
992 def make_load_full_value_message(self, seq, payload):
993 try:
994 return NetCommand(CMD_LOAD_FULL_VALUE, seq, payload)
995 except Exception:
996 return self.make_error_message(seq, get_exception_traceback_str())
998 def make_exit_message(self):
999 try:
1000 net = NetCommand(CMD_EXIT, 0, '')
1002 except:
1003 net = self.make_error_message(0, get_exception_traceback_str())
1005 return net
1007 def make_get_next_statement_targets_message(self, seq, payload):
1008 try:
1009 return NetCommand(CMD_GET_NEXT_STATEMENT_TARGETS, seq, payload)
1010 except Exception:
1011 return self.make_error_message(seq, get_exception_traceback_str())
1014INTERNAL_TERMINATE_THREAD = 1
1015INTERNAL_SUSPEND_THREAD = 2
1018#=======================================================================================================================
1019# InternalThreadCommand
1020#=======================================================================================================================
1021class InternalThreadCommand:
1022 """ internal commands are generated/executed by the debugger.
1024 The reason for their existence is that some commands have to be executed
1025 on specific threads. These are the InternalThreadCommands that get
1026 get posted to PyDB.cmdQueue.
1027 """
1029 def __init__(self, thread_id):
1030 self.thread_id = thread_id
1032 def can_be_executed_by(self, thread_id):
1033 '''By default, it must be in the same thread to be executed
1034 '''
1035 return self.thread_id == thread_id or self.thread_id.endswith('|' + thread_id)
1037 def do_it(self, dbg):
1038 raise NotImplementedError("you have to override do_it")
1041class ReloadCodeCommand(InternalThreadCommand):
1044 def __init__(self, module_name, thread_id):
1045 self.thread_id = thread_id
1046 self.module_name = module_name
1047 self.executed = False
1048 self.lock = thread.allocate_lock()
1051 def can_be_executed_by(self, thread_id):
1052 if self.thread_id == '*':
1053 return True #Any thread can execute it!
1055 return InternalThreadCommand.can_be_executed_by(self, thread_id)
1058 def do_it(self, dbg):
1059 self.lock.acquire()
1060 try:
1061 if self.executed:
1062 return
1063 self.executed = True
1064 finally:
1065 self.lock.release()
1067 module_name = self.module_name
1068 if module_name not in sys.modules:
1069 if '.' in module_name:
1070 new_module_name = module_name.split('.')[-1]
1071 if new_module_name in sys.modules:
1072 module_name = new_module_name
1074 if module_name not in sys.modules:
1075 sys.stderr.write('pydev debugger: Unable to find module to reload: "' + module_name + '".\n')
1076 # Too much info...
1077 # sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n')
1079 else:
1080 sys.stderr.write('pydev debugger: Start reloading module: "' + module_name + '" ... \n')
1081 from _pydevd_bundle import pydevd_reload
1082 if pydevd_reload.xreload(sys.modules[module_name]):
1083 sys.stderr.write('pydev debugger: reload finished\n')
1084 else:
1085 sys.stderr.write('pydev debugger: reload finished without applying any change\n')
1088#=======================================================================================================================
1089# InternalGetThreadStack
1090#=======================================================================================================================
1091class InternalGetThreadStack(InternalThreadCommand):
1092 '''
1093 This command will either wait for a given thread to be paused to get its stack or will provide
1094 it anyways after a timeout (in which case the stack will be gotten but local variables won't
1095 be available and it'll not be possible to interact with the frame as it's not actually
1096 stopped in a breakpoint).
1097 '''
1099 def __init__(self, seq, thread_id, py_db, set_additional_thread_info, timeout=.5):
1100 InternalThreadCommand.__init__(self, thread_id)
1101 self._py_db = weakref.ref(py_db)
1102 self._timeout = time.time() + timeout
1103 self.seq = seq
1104 self._cmd = None
1106 # Note: receives set_additional_thread_info to avoid a circular import
1107 # in this module.
1108 self._set_additional_thread_info = set_additional_thread_info
1110 @overrides(InternalThreadCommand.can_be_executed_by)
1111 def can_be_executed_by(self, _thread_id):
1112 timed_out = time.time() >= self._timeout
1114 py_db = self._py_db()
1115 t = pydevd_find_thread_by_id(self.thread_id)
1116 frame = None
1117 if t and not getattr(t, 'pydev_do_not_trace', None):
1118 additional_info = self._set_additional_thread_info(t)
1119 frame = additional_info.get_topmost_frame(t)
1120 try:
1121 self._cmd = py_db.cmd_factory.make_get_thread_stack_message(
1122 self.seq, self.thread_id, frame, must_be_suspended=not timed_out)
1123 finally:
1124 frame = None
1125 t = None
1127 return self._cmd is not None or timed_out
1129 @overrides(InternalThreadCommand.do_it)
1130 def do_it(self, dbg):
1131 if self._cmd is not None:
1132 dbg.writer.add_command(self._cmd)
1133 self._cmd = None
1136#=======================================================================================================================
1137# InternalRunThread
1138#=======================================================================================================================
1139class InternalRunThread(InternalThreadCommand):
1141 def do_it(self, dbg):
1142 t = pydevd_find_thread_by_id(self.thread_id)
1143 if t:
1144 t.additional_info.pydev_step_cmd = -1
1145 t.additional_info.pydev_step_stop = None
1146 t.additional_info.pydev_state = STATE_RUN
1149#=======================================================================================================================
1150# InternalStepThread
1151#=======================================================================================================================
1152class InternalStepThread(InternalThreadCommand):
1153 def __init__(self, thread_id, cmd_id):
1154 self.thread_id = thread_id
1155 self.cmd_id = cmd_id
1157 def do_it(self, dbg):
1158 t = pydevd_find_thread_by_id(self.thread_id)
1159 if t:
1160 t.additional_info.pydev_step_cmd = self.cmd_id
1161 t.additional_info.pydev_state = STATE_RUN
1164#=======================================================================================================================
1165# InternalSetNextStatementThread
1166#=======================================================================================================================
1167class InternalSetNextStatementThread(InternalThreadCommand):
1168 def __init__(self, thread_id, cmd_id, line, func_name, seq=0):
1169 self.thread_id = thread_id
1170 self.cmd_id = cmd_id
1171 self.line = line
1172 self.seq = seq
1174 if IS_PY2:
1175 if isinstance(func_name, unicode):
1176 # On cython with python 2.X it requires an str, not unicode (but on python 3.3 it should be a str, not bytes).
1177 func_name = func_name.encode('utf-8')
1179 self.func_name = func_name
1181 def do_it(self, dbg):
1182 t = pydevd_find_thread_by_id(self.thread_id)
1183 if t:
1184 t.additional_info.pydev_step_cmd = self.cmd_id
1185 t.additional_info.pydev_next_line = int(self.line)
1186 t.additional_info.pydev_func_name = self.func_name
1187 t.additional_info.pydev_state = STATE_RUN
1188 t.additional_info.pydev_message = str(self.seq)
1191class InternalSmartStepInto(InternalThreadCommand):
1192 def __init__(self, thread_id, frame_id, cmd_id, func_name, line, call_order, start_line, end_line, seq=0):
1193 self.thread_id = thread_id
1194 self.cmd_id = cmd_id
1195 self.line = line
1196 self.start_line = start_line
1197 self.end_line = end_line
1198 self.seq = seq
1199 self.call_order = call_order
1201 if IS_PY2:
1202 if isinstance(func_name, unicode):
1203 # On cython with python 2.X it requires an str, not unicode (but on python 3.3 it should be a str, not bytes).
1204 func_name = func_name.encode('utf-8')
1206 self.func_name = func_name
1208 def do_it(self, dbg):
1209 t = pydevd_find_thread_by_id(self.thread_id)
1210 if t:
1211 t.additional_info.pydev_step_cmd = self.cmd_id
1212 t.additional_info.pydev_next_line = int(self.line)
1213 t.additional_info.pydev_func_name = self.func_name
1214 t.additional_info.pydev_state = STATE_RUN
1215 t.additional_info.pydev_message = str(self.seq)
1216 t.additional_info.pydev_smart_step_context.call_order = int(self.call_order)
1217 t.additional_info.pydev_smart_step_context.start_line = int(self.start_line)
1218 t.additional_info.pydev_smart_step_context.end_line = int(self.end_line)
1221#=======================================================================================================================
1222# InternalGetVariable
1223#=======================================================================================================================
1224class InternalGetVariable(InternalThreadCommand):
1225 """ gets the value of a variable """
1226 def __init__(self, seq, thread_id, frame_id, scope, attrs):
1227 self.sequence = seq
1228 self.thread_id = thread_id
1229 self.frame_id = frame_id
1230 self.scope = scope
1231 self.attributes = attrs
1233 def do_it(self, dbg):
1234 """ Converts request into python variable """
1235 try:
1236 xml = StringIO.StringIO()
1237 xml.write("<xml>")
1238 _typeName, val_dict = pydevd_vars.resolve_compound_variable_fields(self.thread_id, self.frame_id, self.scope, self.attributes)
1239 if val_dict is None:
1240 val_dict = {}
1242 # assume properly ordered if resolver returns 'OrderedDict'
1243 # check type as string to support OrderedDict backport for older Python
1244 keys = dict_keys(val_dict)
1245 if not (_typeName == "OrderedDict" or val_dict.__class__.__name__ == "OrderedDict" or IS_PY36_OR_GREATER):
1246 keys.sort(key=compare_object_attrs_key)
1248 for k in keys:
1249 val = val_dict[k]
1250 evaluate_full_value = pydevd_xml.should_evaluate_full_value(val)
1251 xml.write(pydevd_xml.var_to_xml(val, k, evaluate_full_value=evaluate_full_value))
1253 xml.write("</xml>")
1254 cmd = dbg.cmd_factory.make_get_variable_message(self.sequence, xml.getvalue())
1255 xml.close()
1256 dbg.writer.add_command(cmd)
1257 except Exception:
1258 cmd = dbg.cmd_factory.make_error_message(
1259 self.sequence, "Error resolving variables %s" % (get_exception_traceback_str(),))
1260 dbg.writer.add_command(cmd)
1263#=======================================================================================================================
1264# InternalGetArray
1265#=======================================================================================================================
1266class InternalGetArray(InternalThreadCommand):
1267 def __init__(self, seq, roffset, coffset, rows, cols, format, thread_id, frame_id, scope, attrs):
1268 self.sequence = seq
1269 self.thread_id = thread_id
1270 self.frame_id = frame_id
1271 self.scope = scope
1272 self.name = attrs.split("\t")[-1]
1273 self.attrs = attrs
1274 self.roffset = int(roffset)
1275 self.coffset = int(coffset)
1276 self.rows = int(rows)
1277 self.cols = int(cols)
1278 self.format = format
1280 def do_it(self, dbg):
1281 try:
1282 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1283 var = pydevd_vars.eval_in_context(self.name, frame.f_globals, frame.f_locals)
1284 xml = pydevd_vars.table_like_struct_to_xml(var, self.name, self.roffset, self.coffset, self.rows, self.cols, self.format)
1285 cmd = dbg.cmd_factory.make_get_array_message(self.sequence, xml)
1286 dbg.writer.add_command(cmd)
1287 except:
1288 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error resolving array: " + get_exception_traceback_str())
1289 dbg.writer.add_command(cmd)
1292#=======================================================================================================================
1293# InternalDataViewerAction
1294#=======================================================================================================================
1295class InternalDataViewerAction(InternalThreadCommand):
1296 def __init__(self, sequence, thread_id, frame_id, var, action, args):
1297 self.sequence = sequence
1298 self.thread_id = thread_id
1299 self.frame_id = frame_id
1300 self.var = var
1301 self.action = action
1302 self.args = args
1304 def do_it(self, dbg):
1305 try:
1306 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1307 tmp_var = pydevd_vars.eval_in_context(self.var, frame.f_globals, frame.f_locals)
1309 self.act(tmp_var, self.action, self.args)
1311 cmd = dbg.cmd_factory.make_successful_dataviewer_action_message(
1312 self.sequence,
1313 "Successful execution")
1314 dbg.writer.add_command(cmd)
1316 except Exception as e:
1317 cmd = dbg.cmd_factory.make_error_message(
1318 self.sequence,
1319 type(e).__name__ + "\nError exporting frame: " + get_exception_traceback_str())
1320 dbg.writer.add_command(cmd)
1322 @staticmethod
1323 def act(tmp_var, action, args):
1324 if action == 'EXPORT':
1325 return InternalDataViewerAction.export_action(tmp_var, args)
1327 @staticmethod
1328 def get_type_info(var):
1329 tp = type(var)
1330 tp_name = tp.__name__
1331 tp_qualifier = getattr(tp, "__module__", "")
1333 return tp_qualifier, tp_name
1335 @staticmethod
1336 def export_action(var, args):
1337 # args: (filepath)
1338 filepath = args[0]
1339 extension = filepath.rsplit('.', 1)[1].lower()
1341 tp_qualifier, tp_name = InternalDataViewerAction.get_type_info(var)
1343 if is_pandas_container(tp_qualifier, tp_name, var):
1344 if extension in ('csv', 'tsv'):
1345 delim = ',' if extension == 'csv' else '\t'
1346 var.to_csv(filepath, sep=delim)
1347 else:
1348 raise AttributeError("Format '{}' is not supported".format(extension))
1350 elif is_numpy_container(tp_qualifier, tp_name, var):
1351 try:
1352 import numpy as np
1354 except ImportError:
1355 # Strange. We have an instance of numpy array but we failed to import numpy
1356 raise
1358 if extension in ('csv', 'tsv'):
1359 delim = ',' if extension == 'csv' else '\t'
1360 np.savetxt(filepath, var, fmt="%s", delimiter=delim)
1361 else:
1362 raise AttributeError("Format '{}' is not supported".format(extension))
1364 else:
1365 raise AttributeError("Type {} is not supported".format(type(var)))
1367#=======================================================================================================================
1368# InternalChangeVariable
1369#=======================================================================================================================
1370class InternalChangeVariable(InternalThreadCommand):
1371 """ changes the value of a variable """
1372 def __init__(self, seq, thread_id, frame_id, scope, attr, expression):
1373 self.sequence = seq
1374 self.thread_id = thread_id
1375 self.frame_id = frame_id
1376 self.scope = scope
1377 self.attr = attr
1378 self.expression = expression
1380 def do_it(self, dbg):
1381 """ Converts request into python variable """
1382 try:
1383 result = pydevd_vars.change_attr_expression(self.thread_id, self.frame_id, self.attr, self.expression, dbg)
1384 xml = "<xml>"
1385 xml += pydevd_xml.var_to_xml(result, "")
1386 xml += "</xml>"
1387 cmd = dbg.cmd_factory.make_variable_changed_message(self.sequence, xml)
1388 dbg.writer.add_command(cmd)
1389 except Exception:
1390 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error changing variable attr:%s expression:%s traceback:%s" % (self.attr, self.expression, get_exception_traceback_str()))
1391 dbg.writer.add_command(cmd)
1394#=======================================================================================================================
1395# InternalGetFrame
1396#=======================================================================================================================
1397class InternalGetFrame(InternalThreadCommand):
1398 """ gets the value of a variable """
1399 def __init__(self, seq, thread_id, frame_id):
1400 self.sequence = seq
1401 self.thread_id = thread_id
1402 self.frame_id = frame_id
1404 def do_it(self, dbg):
1405 """ Converts request into python variable """
1406 try:
1407 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1408 if frame is not None:
1409 hidden_ns = pydevd_console_integration.get_ipython_hidden_vars()
1410 xml = "<xml>"
1411 xml += pydevd_xml.frame_vars_to_xml(frame.f_locals, hidden_ns)
1412 del frame
1413 xml += "</xml>"
1414 cmd = dbg.cmd_factory.make_get_frame_message(self.sequence, xml)
1415 dbg.writer.add_command(cmd)
1416 else:
1417 #pydevd_vars.dump_frames(self.thread_id)
1418 #don't print this error: frame not found: means that the client is not synchronized (but that's ok)
1419 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1420 dbg.writer.add_command(cmd)
1421 except:
1422 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error resolving frame: %s from thread: %s" % (self.frame_id, self.thread_id))
1423 dbg.writer.add_command(cmd)
1426class InternalGetSmartStepIntoVariants(InternalThreadCommand):
1427 def __init__(self, seq, thread_id, frame_id, start_line, end_line):
1428 self.sequence = seq
1429 self.thread_id = thread_id
1430 self.frame_id = frame_id
1431 self.start_line = int(start_line)
1432 self.end_line = int(end_line)
1434 def do_it(self, dbg):
1435 try:
1436 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1437 variants = pydevd_bytecode_utils.calculate_smart_step_into_variants(frame, self.start_line, self.end_line)
1438 xml = "<xml>"
1440 for name, is_visited in variants:
1441 xml += '<variant name="%s" isVisited="%s"></variant>' % (quote(name), str(is_visited).lower())
1443 xml += "</xml>"
1444 cmd = NetCommand(CMD_GET_SMART_STEP_INTO_VARIANTS, self.sequence, xml)
1445 dbg.writer.add_command(cmd)
1446 except:
1447 pydevd_log(1, traceback.format_exc())
1448 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error getting smart step into veriants for frame: %s from thread: %s"
1449 % (self.frame_id, self.thread_id))
1450 self._reset_smart_step_context()
1451 dbg.writer.add_command(cmd)
1453 def _reset_smart_step_context(self):
1454 t = pydevd_find_thread_by_id(self.thread_id)
1455 if t:
1456 try:
1457 t.additional_info.pydev_smart_step_context.reset()
1458 except:
1459 pydevd_log(1, "Error while resetting smart step into context for thread %s" % self.thread_id)
1462#=======================================================================================================================
1463# InternalGetNextStatementTargets
1464#=======================================================================================================================
1465class InternalGetNextStatementTargets(InternalThreadCommand):
1466 """ gets the valid line numbers for use with set next statement """
1467 def __init__(self, seq, thread_id, frame_id):
1468 self.sequence = seq
1469 self.thread_id = thread_id
1470 self.frame_id = frame_id
1472 def do_it(self, dbg):
1473 """ Converts request into set of line numbers """
1474 try:
1475 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1476 if frame is not None:
1477 code = frame.f_code
1478 xml = "<xml>"
1479 if hasattr(code, 'co_lnotab'):
1480 lineno = code.co_firstlineno
1481 lnotab = code.co_lnotab
1482 for i in itertools.islice(lnotab, 1, len(lnotab), 2):
1483 if isinstance(i, int):
1484 lineno = lineno + i
1485 else:
1486 # in python 2 elements in co_lnotab are of type str
1487 lineno = lineno + ord(i)
1488 xml += "<line>%d</line>" % (lineno,)
1489 else:
1490 xml += "<line>%d</line>" % (frame.f_lineno,)
1491 del frame
1492 xml += "</xml>"
1493 cmd = dbg.cmd_factory.make_get_next_statement_targets_message(self.sequence, xml)
1494 dbg.writer.add_command(cmd)
1495 else:
1496 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1497 dbg.writer.add_command(cmd)
1498 except:
1499 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error resolving frame: %s from thread: %s" % (self.frame_id, self.thread_id))
1500 dbg.writer.add_command(cmd)
1502#=======================================================================================================================
1503# InternalEvaluateExpression
1504#=======================================================================================================================
1505class InternalEvaluateExpression(InternalThreadCommand):
1506 """ gets the value of a variable """
1508 def __init__(self, seq, thread_id, frame_id, expression, doExec, doTrim, temp_name):
1509 self.sequence = seq
1510 self.thread_id = thread_id
1511 self.frame_id = frame_id
1512 self.expression = expression
1513 self.doExec = doExec
1514 self.doTrim = doTrim
1515 self.temp_name = temp_name
1517 def do_it(self, dbg):
1518 """ Converts request into python variable """
1519 try:
1520 result = pydevd_vars.evaluate_expression(self.thread_id, self.frame_id, self.expression, self.doExec)
1521 if self.temp_name != "":
1522 pydevd_vars.change_attr_expression(self.thread_id, self.frame_id, self.temp_name, self.expression, dbg, result)
1523 xml = "<xml>"
1524 xml += pydevd_xml.var_to_xml(result, self.expression, self.doTrim)
1525 xml += "</xml>"
1526 cmd = dbg.cmd_factory.make_evaluate_expression_message(self.sequence, xml)
1527 dbg.writer.add_command(cmd)
1528 except:
1529 exc = get_exception_traceback_str()
1530 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc)
1531 dbg.writer.add_command(cmd)
1533#=======================================================================================================================
1534# InternalGetCompletions
1535#=======================================================================================================================
1536class InternalGetCompletions(InternalThreadCommand):
1537 """ Gets the completions in a given scope """
1539 def __init__(self, seq, thread_id, frame_id, act_tok):
1540 self.sequence = seq
1541 self.thread_id = thread_id
1542 self.frame_id = frame_id
1543 self.act_tok = act_tok
1546 def do_it(self, dbg):
1547 """ Converts request into completions """
1548 try:
1549 remove_path = None
1550 try:
1552 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1553 if frame is not None:
1555 msg = _pydev_completer.generate_completions_as_xml(frame, self.act_tok)
1557 cmd = dbg.cmd_factory.make_get_completions_message(self.sequence, msg)
1558 dbg.writer.add_command(cmd)
1559 else:
1560 cmd = dbg.cmd_factory.make_error_message(self.sequence, "InternalGetCompletions: Frame not found: %s from thread: %s" % (self.frame_id, self.thread_id))
1561 dbg.writer.add_command(cmd)
1564 finally:
1565 if remove_path is not None:
1566 sys.path.remove(remove_path)
1568 except:
1569 exc = get_exception_traceback_str()
1570 sys.stderr.write('%s\n' % (exc,))
1571 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc)
1572 dbg.writer.add_command(cmd)
1575# =======================================================================================================================
1576# InternalGetDescription
1577# =======================================================================================================================
1578class InternalGetDescription(InternalThreadCommand):
1579 """ Fetch the variable description stub from the debug console
1580 """
1582 def __init__(self, seq, thread_id, frame_id, expression):
1583 self.sequence = seq
1584 self.thread_id = thread_id
1585 self.frame_id = frame_id
1586 self.expression = expression
1588 def do_it(self, dbg):
1589 """ Get completions and write back to the client
1590 """
1591 try:
1592 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1593 description = pydevd_console.get_description(frame, self.thread_id, self.frame_id, self.expression)
1594 description = pydevd_xml.make_valid_xml_value(quote(description, '/>_= \t'))
1595 description_xml = '<xml><var name="" type="" value="%s"/></xml>' % description
1596 cmd = dbg.cmd_factory.make_get_description_message(self.sequence, description_xml)
1597 dbg.writer.add_command(cmd)
1598 except:
1599 exc = get_exception_traceback_str()
1600 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching description" + exc)
1601 dbg.writer.add_command(cmd)
1604#=======================================================================================================================
1605# InternalGetBreakpointException
1606#=======================================================================================================================
1607class InternalGetBreakpointException(InternalThreadCommand):
1608 """ Send details of exception raised while evaluating conditional breakpoint """
1609 def __init__(self, thread_id, exc_type, stacktrace):
1610 self.sequence = 0
1611 self.thread_id = thread_id
1612 self.stacktrace = stacktrace
1613 self.exc_type = exc_type
1615 def do_it(self, dbg):
1616 try:
1617 callstack = "<xml>"
1619 makeValid = pydevd_xml.make_valid_xml_value
1621 for filename, line, methodname, methodobj in self.stacktrace:
1622 if file_system_encoding.lower() != "utf-8" and hasattr(filename, "decode"):
1623 # filename is a byte string encoded using the file system encoding
1624 # convert it to utf8
1625 filename = filename.decode(file_system_encoding).encode("utf-8")
1627 callstack += '<frame thread_id = "%s" file="%s" line="%s" name="%s" obj="%s" />' \
1628 % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj))
1629 callstack += "</xml>"
1631 cmd = dbg.cmd_factory.make_send_breakpoint_exception_message(self.sequence, self.exc_type + "\t" + callstack)
1632 dbg.writer.add_command(cmd)
1633 except:
1634 exc = get_exception_traceback_str()
1635 sys.stderr.write('%s\n' % (exc,))
1636 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Exception: " + exc)
1637 dbg.writer.add_command(cmd)
1640#=======================================================================================================================
1641# InternalSendCurrExceptionTrace
1642#=======================================================================================================================
1643class InternalSendCurrExceptionTrace(InternalThreadCommand):
1644 """ Send details of the exception that was caught and where we've broken in.
1645 """
1646 def __init__(self, thread_id, arg, curr_frame_id):
1647 '''
1648 :param arg: exception type, description, traceback object
1649 '''
1650 self.sequence = 0
1651 self.thread_id = thread_id
1652 self.curr_frame_id = curr_frame_id
1653 self.arg = arg
1655 def do_it(self, dbg):
1656 try:
1657 cmd = dbg.cmd_factory.make_send_curr_exception_trace_message(self.sequence, self.thread_id, self.curr_frame_id, *self.arg)
1658 del self.arg
1659 dbg.writer.add_command(cmd)
1660 except:
1661 exc = get_exception_traceback_str()
1662 sys.stderr.write('%s\n' % (exc,))
1663 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Current Exception Trace: " + exc)
1664 dbg.writer.add_command(cmd)
1666#=======================================================================================================================
1667# InternalSendCurrExceptionTraceProceeded
1668#=======================================================================================================================
1669class InternalSendCurrExceptionTraceProceeded(InternalThreadCommand):
1670 """ Send details of the exception that was caught and where we've broken in.
1671 """
1672 def __init__(self, thread_id):
1673 self.sequence = 0
1674 self.thread_id = thread_id
1676 def do_it(self, dbg):
1677 try:
1678 cmd = dbg.cmd_factory.make_send_curr_exception_trace_proceeded_message(self.sequence, self.thread_id)
1679 dbg.writer.add_command(cmd)
1680 except:
1681 exc = get_exception_traceback_str()
1682 sys.stderr.write('%s\n' % (exc,))
1683 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc)
1684 dbg.writer.add_command(cmd)
1687#=======================================================================================================================
1688# InternalEvaluateConsoleExpression
1689#=======================================================================================================================
1690class InternalEvaluateConsoleExpression(InternalThreadCommand):
1691 """ Execute the given command in the debug console """
1693 def __init__(self, seq, thread_id, frame_id, line, buffer_output=True):
1694 self.sequence = seq
1695 self.thread_id = thread_id
1696 self.frame_id = frame_id
1697 self.line = line
1698 self.buffer_output = buffer_output
1700 def do_it(self, dbg):
1701 """ Create an XML for console output, error and more (true/false)
1702 <xml>
1703 <output message=output_message></output>
1704 <error message=error_message></error>
1705 <more>true/false</more>
1706 </xml>
1707 """
1708 try:
1709 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1710 if frame is not None:
1711 console_message = pydevd_console.execute_console_command(
1712 frame, self.thread_id, self.frame_id, self.line, self.buffer_output)
1714 cmd = dbg.cmd_factory.make_send_console_message(self.sequence, console_message.to_xml())
1715 else:
1716 from _pydevd_bundle.pydevd_console import ConsoleMessage
1717 console_message = ConsoleMessage()
1718 console_message.add_console_message(
1719 pydevd_console.CONSOLE_ERROR,
1720 "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id),
1721 )
1722 cmd = dbg.cmd_factory.make_error_message(self.sequence, console_message.to_xml())
1723 except:
1724 exc = get_exception_traceback_str()
1725 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc)
1726 dbg.writer.add_command(cmd)
1729#=======================================================================================================================
1730# InternalRunCustomOperation
1731#=======================================================================================================================
1732class InternalRunCustomOperation(InternalThreadCommand):
1733 """ Run a custom command on an expression
1734 """
1735 def __init__(self, seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname):
1736 self.sequence = seq
1737 self.thread_id = thread_id
1738 self.frame_id = frame_id
1739 self.scope = scope
1740 self.attrs = attrs
1741 self.style = style
1742 self.code_or_file = unquote_plus(encoded_code_or_file)
1743 self.fnname = fnname
1745 def do_it(self, dbg):
1746 try:
1747 res = pydevd_vars.custom_operation(self.thread_id, self.frame_id, self.scope, self.attrs,
1748 self.style, self.code_or_file, self.fnname)
1749 resEncoded = quote_plus(res)
1750 cmd = dbg.cmd_factory.make_custom_operation_message(self.sequence, resEncoded)
1751 dbg.writer.add_command(cmd)
1752 except:
1753 exc = get_exception_traceback_str()
1754 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in running custom operation" + exc)
1755 dbg.writer.add_command(cmd)
1758#=======================================================================================================================
1759# InternalConsoleGetCompletions
1760#=======================================================================================================================
1761class InternalConsoleGetCompletions(InternalThreadCommand):
1762 """ Fetch the completions in the debug console
1763 """
1764 def __init__(self, seq, thread_id, frame_id, act_tok):
1765 self.sequence = seq
1766 self.thread_id = thread_id
1767 self.frame_id = frame_id
1768 self.act_tok = act_tok
1770 def do_it(self, dbg):
1771 """ Get completions and write back to the client
1772 """
1773 try:
1774 frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
1775 completions_xml = pydevd_console.get_completions(frame, self.act_tok)
1776 cmd = dbg.cmd_factory.make_send_console_message(self.sequence, completions_xml)
1777 dbg.writer.add_command(cmd)
1778 except:
1779 exc = get_exception_traceback_str()
1780 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching completions" + exc)
1781 dbg.writer.add_command(cmd)
1784#=======================================================================================================================
1785# InternalConsoleExec
1786#=======================================================================================================================
1787class InternalConsoleExec(InternalThreadCommand):
1788 """ gets the value of a variable """
1790 def __init__(self, seq, thread_id, frame_id, expression):
1791 self.sequence = seq
1792 self.thread_id = thread_id
1793 self.frame_id = frame_id
1794 self.expression = expression
1796 def do_it(self, dbg):
1797 """ Converts request into python variable """
1798 try:
1799 try:
1800 #don't trace new threads created by console command
1801 disable_trace_thread_modules()
1803 result = pydevd_console_integration.console_exec(self.thread_id, self.frame_id, self.expression, dbg)
1804 xml = "<xml>"
1805 xml += pydevd_xml.var_to_xml(result, "")
1806 xml += "</xml>"
1807 cmd = dbg.cmd_factory.make_evaluate_expression_message(self.sequence, xml)
1808 dbg.writer.add_command(cmd)
1809 except:
1810 exc = get_exception_traceback_str()
1811 sys.stderr.write('%s\n' % (exc,))
1812 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating console expression " + exc)
1813 dbg.writer.add_command(cmd)
1814 finally:
1815 enable_trace_thread_modules()
1817 sys.stderr.flush()
1818 sys.stdout.flush()
1821#=======================================================================================================================
1822# InternalLoadFullValue
1823#=======================================================================================================================
1824class InternalLoadFullValue(InternalThreadCommand):
1825 """
1826 Loads values asynchronously
1827 """
1828 def __init__(self, seq, thread_id, frame_id, vars):
1829 self.sequence = seq
1830 self.thread_id = thread_id
1831 self.frame_id = frame_id
1832 self.vars = vars
1834 def do_it(self, dbg):
1835 """Starts a thread that will load values asynchronously"""
1836 try:
1837 var_objects = []
1838 for variable in self.vars:
1839 variable = variable.strip()
1840 if len(variable) > 0:
1841 if '\t' in variable: # there are attributes beyond scope
1842 scope, attrs = variable.split('\t', 1)
1843 name = attrs[0]
1844 else:
1845 scope, attrs = (variable, None)
1846 name = scope
1847 var_obj = pydevd_vars.getVariable(self.thread_id, self.frame_id, scope, attrs)
1848 var_objects.append((var_obj, name))
1850 t = GetValueAsyncThreadDebug(dbg, self.sequence, var_objects)
1851 t.start()
1852 except:
1853 exc = get_exception_traceback_str()
1854 sys.stderr.write('%s\n' % (exc,))
1855 cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating variable %s " % exc)
1856 dbg.writer.add_command(cmd)
1859class AbstractGetValueAsyncThread(PyDBDaemonThread):
1860 """
1861 Abstract class for a thread, which evaluates values for async variables
1862 """
1863 def __init__(self, frame_accessor, seq, var_objects):
1864 PyDBDaemonThread.__init__(self)
1865 self.frame_accessor = frame_accessor
1866 self.seq = seq
1867 self.var_objs = var_objects
1868 self.cancel_event = threading.Event()
1870 def send_result(self, xml):
1871 raise NotImplementedError()
1873 @overrides(PyDBDaemonThread._on_run)
1874 def _on_run(self):
1875 start = time.time()
1876 xml = StringIO.StringIO()
1877 xml.write("<xml>")
1878 for (var_obj, name) in self.var_objs:
1879 current_time = time.time()
1880 if current_time - start > ASYNC_EVAL_TIMEOUT_SEC or self.cancel_event.is_set():
1881 break
1882 xml.write(pydevd_xml.var_to_xml(var_obj, name, evaluate_full_value=True))
1883 xml.write("</xml>")
1884 self.send_result(xml)
1885 xml.close()
1888class GetValueAsyncThreadDebug(AbstractGetValueAsyncThread):
1889 """
1890 A thread for evaluation async values, which returns result for debugger
1891 Create message and send it via writer thread
1892 """
1893 def send_result(self, xml):
1894 if self.frame_accessor is not None:
1895 cmd = self.frame_accessor.cmd_factory.make_load_full_value_message(self.seq, xml.getvalue())
1896 self.frame_accessor.writer.add_command(cmd)
1899class GetValueAsyncThreadConsole(AbstractGetValueAsyncThread):
1900 """
1901 A thread for evaluation async values, which returns result for Console
1902 Send result directly to Console's server
1903 """
1904 def send_result(self, xml):
1905 if self.frame_accessor is not None:
1906 self.frame_accessor.ReturnFullValue(self.seq, xml.getvalue())
1909#=======================================================================================================================
1910# pydevd_find_thread_by_id
1911#=======================================================================================================================
1912def pydevd_find_thread_by_id(thread_id):
1913 try:
1914 # there was a deadlock here when I did not remove the tracing function when thread was dead
1915 threads = threading.enumerate()
1916 for i in threads:
1917 tid = get_thread_id(i)
1918 if thread_id == tid or thread_id.endswith('|' + tid):
1919 return i
1921 # This can happen when a request comes for a thread which was previously removed.
1922 pydevd_log(1, "Could not find thread %s\n" % thread_id)
1923 pydevd_log(1, "Available: %s\n" % [get_thread_id(t) for t in threads])
1924 except:
1925 traceback.print_exc()
1927 return None