blob: 1733c26b5e91782b1de31939404e9c22a382bd62 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001#IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe
Tor Norbye1aa2e092014-08-20 17:01:23 -07002from __future__ import nested_scopes # Jython 2.1 support
3
Tor Norbyec667c1f2014-05-28 17:06:51 -07004import traceback
5
Tor Norbye3a2425a2013-11-04 10:16:08 -08006from django_debug import DjangoLineBreakpoint
7from pydevd_signature import SignatureFactory
8from pydevd_frame import add_exception_to_frame
Tor Norbye3a2425a2013-11-04 10:16:08 -08009import pydev_imports
10from pydevd_breakpoints import * #@UnusedWildImport
11import fix_getpass
Tor Norbye3a2425a2013-11-04 10:16:08 -080012from pydevd_comm import CMD_CHANGE_VARIABLE, \
13 CMD_EVALUATE_EXPRESSION, \
14 CMD_EXEC_EXPRESSION, \
15 CMD_GET_COMPLETIONS, \
16 CMD_GET_FRAME, \
17 CMD_GET_VARIABLE, \
18 CMD_LIST_THREADS, \
19 CMD_REMOVE_BREAK, \
20 CMD_RUN, \
21 CMD_SET_BREAK, \
22 CMD_SET_NEXT_STATEMENT,\
23 CMD_STEP_INTO, \
24 CMD_STEP_OVER, \
25 CMD_STEP_RETURN, \
26 CMD_THREAD_CREATE, \
27 CMD_THREAD_KILL, \
28 CMD_THREAD_RUN, \
29 CMD_THREAD_SUSPEND, \
30 CMD_RUN_TO_LINE, \
31 CMD_RELOAD_CODE, \
32 CMD_VERSION, \
33 CMD_CONSOLE_EXEC, \
34 CMD_ADD_EXCEPTION_BREAK, \
35 CMD_REMOVE_EXCEPTION_BREAK, \
36 CMD_LOAD_SOURCE, \
37 CMD_ADD_DJANGO_EXCEPTION_BREAK, \
38 CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
39 CMD_SMART_STEP_INTO,\
Tor Norbye1aa2e092014-08-20 17:01:23 -070040 InternalChangeVariable, \
Tor Norbye3a2425a2013-11-04 10:16:08 -080041 InternalGetCompletions, \
42 InternalEvaluateExpression, \
43 InternalConsoleExec, \
44 InternalGetFrame, \
45 InternalGetVariable, \
46 InternalTerminateThread, \
47 InternalRunThread, \
48 InternalStepThread, \
49 NetCommand, \
50 NetCommandFactory, \
51 PyDBDaemonThread, \
52 _queue, \
53 ReaderThread, \
54 SetGlobalDebugger, \
55 WriterThread, \
56 PydevdFindThreadById, \
57 PydevdLog, \
58 StartClient, \
59 StartServer, \
Tor Norbye1aa2e092014-08-20 17:01:23 -070060 InternalSetNextStatementThread, \
61 ReloadCodeCommand, \
62 CMD_SET_PY_EXCEPTION, \
63 CMD_IGNORE_THROWN_EXCEPTION_AT,\
64 InternalGetBreakpointException, \
65 InternalSendCurrExceptionTrace,\
66 InternalSendCurrExceptionTraceProceeded,\
67 CMD_ENABLE_DONT_TRACE, \
68 CMD_GET_FILE_CONTENTS,\
69 CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\
70 InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\
71 InternalConsoleGetCompletions
72
Tor Norbye3a2425a2013-11-04 10:16:08 -080073from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
74import pydevd_file_utils
75import pydevd_vars
Tor Norbye3a2425a2013-11-04 10:16:08 -080076import pydevd_vm_type
77import pydevd_tracing
78import pydevd_io
Tor Norbye3a2425a2013-11-04 10:16:08 -080079from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
Tor Norbyec667c1f2014-05-28 17:06:51 -070080from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
Tor Norbye1aa2e092014-08-20 17:01:23 -070081import pydevd_dont_trace
82import pydevd_traceproperty
Tor Norbyec667c1f2014-05-28 17:06:51 -070083
Tor Norbye1aa2e092014-08-20 17:01:23 -070084from _pydev_imps import _pydev_time as time
Tor Norbye3a2425a2013-11-04 10:16:08 -080085
86if USE_LIB_COPY:
Tor Norbye3a2425a2013-11-04 10:16:08 -080087 import _pydev_threading as threading
88else:
Tor Norbye3a2425a2013-11-04 10:16:08 -080089 import threading
90
91import os
92
93
94threadingEnumerate = threading.enumerate
95threadingCurrentThread = threading.currentThread
96
Tor Norbye1aa2e092014-08-20 17:01:23 -070097try:
98 'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread).
99except:
100 pass
Tor Norbye3a2425a2013-11-04 10:16:08 -0800101
102DONT_TRACE = {
Tor Norbyec667c1f2014-05-28 17:06:51 -0700103 # commonly used things from the stdlib that we don't want to trace
Tor Norbye3a2425a2013-11-04 10:16:08 -0800104 'Queue.py':1,
105 'queue.py':1,
106 'socket.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700107 'weakref.py':1,
108 'linecache.py':1,
109 'threading.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800110
111 #things from pydev that we don't want to trace
Tor Norbye1aa2e092014-08-20 17:01:23 -0700112 '_pydev_execfile.py':1,
113 '_pydev_jython_execfile.py':1,
114 '_pydev_threading':1,
115 'django_debug.py':1,
116 'django_frame.py':1,
117 'pydev_log.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700118 'pydevd.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800119 'pydevd_additional_thread_info.py':1,
120 'pydevd_comm.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700121 'pydevd_console.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800122 'pydevd_constants.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700123 'pydevd_custom_frames.py':1,
124 'pydevd_dont_trace.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800125 'pydevd_exec.py':1,
126 'pydevd_exec2.py':1,
127 'pydevd_file_utils.py':1,
128 'pydevd_frame.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700129 'pydevd_import_class.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800130 'pydevd_io.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700131 'pydevd_psyco_stub.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700132 'pydevd_referrers.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700133 'pydevd_reload.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800134 'pydevd_resolver.py':1 ,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700135 'pydevd_save_locals.py':1 ,
136 'pydevd_signature.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700137 'pydevd_stackless.py':1 ,
138 'pydevd_traceproperty.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800139 'pydevd_tracing.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800140 'pydevd_utils.py':1,
141 'pydevd_vars.py':1,
142 'pydevd_vm_type.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700143 'pydevd_xml.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700144 }
Tor Norbye3a2425a2013-11-04 10:16:08 -0800145
146if IS_PY3K:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700147 # if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800148 DONT_TRACE['io.py'] = 1
149
Tor Norbyec667c1f2014-05-28 17:06:51 -0700150 # Don't trace common encodings too
151 DONT_TRACE['cp1252.py'] = 1
152 DONT_TRACE['utf_8.py'] = 1
153
Tor Norbye3a2425a2013-11-04 10:16:08 -0800154
155connected = False
156bufferStdOutToServer = False
157bufferStdErrToServer = False
158remote = False
159
Tor Norbyec667c1f2014-05-28 17:06:51 -0700160from _pydev_filesystem_encoding import getfilesystemencoding
161file_system_encoding = getfilesystemencoding()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800162
Tor Norbye1aa2e092014-08-20 17:01:23 -0700163
164# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
165# It is required to debug threads started by start_new_thread in Python 3.4
166_temp = threading.Thread()
167if hasattr(_temp, '_is_stopped'): # Python 3.4 has this
168 def isThreadAlive(t):
169 try:
170 return not t._is_stopped
171 except:
172 return t.isAlive()
173
174elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this
175 def isThreadAlive(t):
176 try:
177 return not t._Thread__stopped
178 except:
179 return t.isAlive()
180
181else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case.
182 def isThreadAlive(t):
183 return t.isAlive()
184del _temp
Tor Norbye3a2425a2013-11-04 10:16:08 -0800185
186#=======================================================================================================================
187# PyDBCommandThread
188#=======================================================================================================================
189class PyDBCommandThread(PyDBDaemonThread):
190
191 def __init__(self, pyDb):
192 PyDBDaemonThread.__init__(self)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700193 self._py_db_command_thread_event = pyDb._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800194 self.pyDb = pyDb
195 self.setName('pydevd.CommandThread')
196
197 def OnRun(self):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700198 for i in xrange(1, 10):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800199 time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
200 if self.killReceived:
201 return
202
203 if self.dontTraceMe:
204 self.pyDb.SetTrace(None) # no debugging on this thread
205
206 try:
207 while not self.killReceived:
208 try:
209 self.pyDb.processInternalCommands()
210 except:
211 PydevdLog(0, 'Finishing debug communication...(2)')
Tor Norbyec667c1f2014-05-28 17:06:51 -0700212 self._py_db_command_thread_event.clear()
213 self._py_db_command_thread_event.wait(0.5)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800214 except:
215 pydev_log.debug(sys.exc_info()[0])
216
217 #only got this error in interpreter shutdown
218 #PydevdLog(0, 'Finishing debug communication...(3)')
219
220
221def killAllPydevThreads():
222 threads = threadingEnumerate()
223 for t in threads:
224 if hasattr(t, 'doKillPydevThread'):
225 t.doKillPydevThread()
Tor Norbye1aa2e092014-08-20 17:01:23 -0700226
Tor Norbye3a2425a2013-11-04 10:16:08 -0800227
228#=======================================================================================================================
229# PyDBCheckAliveThread
230#=======================================================================================================================
231class PyDBCheckAliveThread(PyDBDaemonThread):
232
233 def __init__(self, pyDb):
234 PyDBDaemonThread.__init__(self)
235 self.pyDb = pyDb
236 self.setDaemon(False)
237 self.setName('pydevd.CheckAliveThread')
238
239 def OnRun(self):
240 if self.dontTraceMe:
241 self.pyDb.SetTrace(None) # no debugging on this thread
242 while not self.killReceived:
243 if not self.pyDb.haveAliveThreads():
244 try:
245 pydev_log.debug("No alive threads, finishing debug session")
246 self.pyDb.FinishDebuggingSession()
247 killAllPydevThreads()
248 except:
249 traceback.print_exc()
250
Tor Norbye3a2425a2013-11-04 10:16:08 -0800251 self.killReceived = True
252 return
253
254 time.sleep(0.3)
255
256 def doKillPydevThread(self):
257 pass
258
Tor Norbye3a2425a2013-11-04 10:16:08 -0800259
Tor Norbyec667c1f2014-05-28 17:06:51 -0700260
Tor Norbye3a2425a2013-11-04 10:16:08 -0800261#=======================================================================================================================
262# PyDB
263#=======================================================================================================================
264class PyDB:
265 """ Main debugging class
266 Lots of stuff going on here:
267
268 PyDB starts two threads on startup that connect to remote debugger (RDB)
269 The threads continuously read & write commands to RDB.
270 PyDB communicates with these threads through command queues.
271 Every RDB command is processed by calling processNetCommand.
272 Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue
273
274 Some commands need to be executed on the right thread (suspend/resume & friends)
275 These are placed on the internal command queue.
276 """
277
Tor Norbye3a2425a2013-11-04 10:16:08 -0800278
279 def __init__(self):
280 SetGlobalDebugger(self)
281 pydevd_tracing.ReplaceSysSetTraceFunc()
282 self.reader = None
283 self.writer = None
284 self.quitting = None
285 self.cmdFactory = NetCommandFactory()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700286 self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread
Tor Norbye1aa2e092014-08-20 17:01:23 -0700287
Tor Norbye3a2425a2013-11-04 10:16:08 -0800288 self.breakpoints = {}
289 self.django_breakpoints = {}
Tor Norbye1aa2e092014-08-20 17:01:23 -0700290
291 self.file_to_id_to_line_breakpoint = {}
292 self.file_to_id_to_django_breakpoint = {}
293
294 # Note: breakpoints dict should not be mutated: a copy should be created
295 # and later it should be assigned back (to prevent concurrency issues).
296 self.break_on_uncaught_exceptions = {}
297 self.break_on_caught_exceptions = {}
298
Tor Norbye3a2425a2013-11-04 10:16:08 -0800299 self.django_exception_break = {}
300 self.readyToRun = False
301 self._main_lock = threading.Lock()
302 self._lock_running_thread_ids = threading.Lock()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700303 self._py_db_command_thread_event = threading.Event()
304 CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800305 self._finishDebuggingSession = False
306 self._terminationEventSent = False
Tor Norbye3a2425a2013-11-04 10:16:08 -0800307 self.signature_factory = None
308 self.SetTrace = pydevd_tracing.SetTrace
Tor Norbye1aa2e092014-08-20 17:01:23 -0700309 self.break_on_exceptions_thrown_in_same_context = False
310 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
311
312 # Suspend debugger even if breakpoint condition raises an exception
313 SUSPEND_ON_BREAKPOINT_EXCEPTION = True
314 self.suspend_on_breakpoint_exception = SUSPEND_ON_BREAKPOINT_EXCEPTION
315
316 # By default user can step into properties getter/setter/deleter methods
317 self.disable_property_trace = False
318 self.disable_property_getter_trace = False
319 self.disable_property_setter_trace = False
320 self.disable_property_deleter_trace = False
Tor Norbye3a2425a2013-11-04 10:16:08 -0800321
322 #this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
323 #acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
324 #find that thread alive anymore, we must remove it from this list and make the java side know that the thread
325 #was killed.
326 self._running_thread_ids = {}
Tor Norbye1aa2e092014-08-20 17:01:23 -0700327 self._set_breakpoints_with_id = False
328
329 # This attribute holds the file-> lines which have an @IgnoreException.
330 self.filename_to_lines_where_exceptions_are_ignored = {}
331
Tor Norbye3a2425a2013-11-04 10:16:08 -0800332
333 def haveAliveThreads(self):
334 for t in threadingEnumerate():
Tor Norbye92584642014-04-17 08:39:25 -0700335 if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t) and not t.isDaemon():
Tor Norbye3a2425a2013-11-04 10:16:08 -0800336 return True
337
338 return False
339
340 def FinishDebuggingSession(self):
341 self._finishDebuggingSession = True
342
343 def acquire(self):
344 if PyDBUseLocks:
345 self.lock.acquire()
346 return True
347
348 def release(self):
349 if PyDBUseLocks:
350 self.lock.release()
351 return True
352
353 def initializeNetwork(self, sock):
354 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700355 sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it
Tor Norbye3a2425a2013-11-04 10:16:08 -0800356 except:
357 pass
358 self.writer = WriterThread(sock)
359 self.reader = ReaderThread(sock)
360 self.writer.start()
361 self.reader.start()
362
Tor Norbyec667c1f2014-05-28 17:06:51 -0700363 time.sleep(0.1) # give threads time to start
Tor Norbye3a2425a2013-11-04 10:16:08 -0800364
365 def connect(self, host, port):
366 if host:
367 s = StartClient(host, port)
368 else:
369 s = StartServer(port)
370
371 self.initializeNetwork(s)
372
373
374 def getInternalQueue(self, thread_id):
375 """ returns internal command queue for a given thread.
376 if new queue is created, notify the RDB about it """
Tor Norbyec667c1f2014-05-28 17:06:51 -0700377 if thread_id.startswith('__frame__'):
378 thread_id = thread_id[thread_id.rfind('|') + 1:]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800379 try:
380 return self._cmd_queue[thread_id]
381 except KeyError:
382 return self._cmd_queue.setdefault(thread_id, _queue.Queue()) #@UndefinedVariable
383
384
385 def postInternalCommand(self, int_cmd, thread_id):
386 """ if thread_id is *, post to all """
387 if thread_id == "*":
Tor Norbyec667c1f2014-05-28 17:06:51 -0700388 threads = threadingEnumerate()
389 for t in threads:
390 thread_name = t.getName()
391 if not thread_name.startswith('pydevd.') or thread_name == 'pydevd.CommandThread':
392 thread_id = GetThreadId(t)
393 queue = self.getInternalQueue(thread_id)
394 queue.put(int_cmd)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800395
396 else:
397 queue = self.getInternalQueue(thread_id)
398 queue.put(int_cmd)
399
400 def checkOutputRedirect(self):
401 global bufferStdOutToServer
402 global bufferStdErrToServer
403
404 if bufferStdOutToServer:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700405 initStdoutRedirect()
406 self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
Tor Norbye3a2425a2013-11-04 10:16:08 -0800407
408 if bufferStdErrToServer:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700409 initStderrRedirect()
410 self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
Tor Norbye3a2425a2013-11-04 10:16:08 -0800411
412 def checkOutput(self, out, outCtx):
413 '''Checks the output to see if we have to send some buffered output to the debug server
414
415 @param out: sys.stdout or sys.stderr
416 @param outCtx: the context indicating: 1=stdout and 2=stderr (to know the colors to write it)
417 '''
418
419 try:
420 v = out.getvalue()
421
422 if v:
423 self.cmdFactory.makeIoMessage(v, outCtx, self)
424 except:
425 traceback.print_exc()
426
427
428 def processInternalCommands(self):
429 '''This function processes internal commands
430 '''
Tor Norbye3a2425a2013-11-04 10:16:08 -0800431 self._main_lock.acquire()
432 try:
433
434 self.checkOutputRedirect()
435
Tor Norbyec667c1f2014-05-28 17:06:51 -0700436 curr_thread_id = GetThreadId(threadingCurrentThread())
437 program_threads_alive = {}
438 all_threads = threadingEnumerate()
439 program_threads_dead = []
Tor Norbye3a2425a2013-11-04 10:16:08 -0800440 self._lock_running_thread_ids.acquire()
441 try:
442 for t in all_threads:
443 thread_id = GetThreadId(t)
444
Tor Norbye92584642014-04-17 08:39:25 -0700445 if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800446 program_threads_alive[thread_id] = t
447
448 if not DictContains(self._running_thread_ids, thread_id):
449 if not hasattr(t, 'additionalInfo'):
Tor Norbyec667c1f2014-05-28 17:06:51 -0700450 # see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329
451 # Let's create the additional info right away!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800452 t.additionalInfo = PyDBAdditionalThreadInfo()
453 self._running_thread_ids[thread_id] = t
454 self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t))
455
456
457 queue = self.getInternalQueue(thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700458 cmdsToReadd = [] # some commands must be processed by the thread itself... if that's the case,
459 # we will re-add the commands to the queue after executing.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800460 try:
461 while True:
462 int_cmd = queue.get(False)
463 if int_cmd.canBeExecutedBy(curr_thread_id):
464 PydevdLog(2, "processing internal command ", str(int_cmd))
465 int_cmd.doIt(self)
466 else:
467 PydevdLog(2, "NOT processing internal command ", str(int_cmd))
468 cmdsToReadd.append(int_cmd)
469
470 except _queue.Empty: #@UndefinedVariable
471 for int_cmd in cmdsToReadd:
472 queue.put(int_cmd)
473 # this is how we exit
474
475
476 thread_ids = list(self._running_thread_ids.keys())
477 for tId in thread_ids:
478 if not DictContains(program_threads_alive, tId):
479 program_threads_dead.append(tId)
480 finally:
481 self._lock_running_thread_ids.release()
482
483 for tId in program_threads_dead:
484 try:
485 self.processThreadNotAlive(tId)
486 except:
487 sys.stderr.write('Error iterating through %s (%s) - %s\n' % (
488 program_threads_alive, program_threads_alive.__class__, dir(program_threads_alive)))
489 raise
490
491
492 if len(program_threads_alive) == 0:
493 self.FinishDebuggingSession()
494 for t in all_threads:
495 if hasattr(t, 'doKillPydevThread'):
496 t.doKillPydevThread()
497
498 finally:
499 self._main_lock.release()
500
501
Tor Norbyec667c1f2014-05-28 17:06:51 -0700502 def setTracingForUntracedContexts(self, ignore_frame=None, overwrite_prev_trace=False):
503 # Enable the tracing for existing threads (because there may be frames being executed that
504 # are currently untraced).
Tor Norbye3a2425a2013-11-04 10:16:08 -0800505 threads = threadingEnumerate()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700506 try:
507 for t in threads:
508 if not t.getName().startswith('pydevd.'):
509 # TODO: optimize so that we only actually add that tracing if it's in
510 # the new breakpoint context.
511 additionalInfo = None
512 try:
513 additionalInfo = t.additionalInfo
514 except AttributeError:
515 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800516
Tor Norbyec667c1f2014-05-28 17:06:51 -0700517 if additionalInfo is not None:
518 for frame in additionalInfo.IterFrames():
519 if frame is not ignore_frame:
520 self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
521 finally:
522 frame = None
523 t = None
524 threads = None
525 additionalInfo = None
Tor Norbye3a2425a2013-11-04 10:16:08 -0800526
527
Tor Norbye1aa2e092014-08-20 17:01:23 -0700528 def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
529 break_dict = {}
530 for breakpoint_id, pybreakpoint in DictIterItems(id_to_breakpoint):
531 break_dict[pybreakpoint.line] = pybreakpoint
532
533 breakpoints[file] = break_dict
534
535
536 def add_break_on_exception(
537 self,
538 exception,
539 notify_always,
540 notify_on_terminate,
541 notify_on_first_raise_only,
542 ):
543 eb = ExceptionBreakpoint(
544 exception,
545 notify_always,
546 notify_on_terminate,
547 notify_on_first_raise_only,
548 )
549
550 if eb.notify_on_terminate:
551 cp = self.break_on_uncaught_exceptions.copy()
552 cp[exception] = eb
553 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
554 pydev_log.error("Exceptions to hook on terminate: %s\n" % (cp,))
555 self.break_on_uncaught_exceptions = cp
556
557 if eb.notify_always:
558 cp = self.break_on_caught_exceptions.copy()
559 cp[exception] = eb
560 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
561 pydev_log.error("Exceptions to hook always: %s\n" % (cp,))
562 self.break_on_caught_exceptions = cp
563
564 return eb
565
566 def update_after_exceptions_added(self, added):
567 updated_on_caught = False
568 updated_on_uncaught = False
569
570 for eb in added:
571 if not updated_on_uncaught and eb.notify_on_terminate:
572 updated_on_uncaught = True
573 update_exception_hook(self)
574
575 if not updated_on_caught and eb.notify_always:
576 updated_on_caught = True
577 self.setTracingForUntracedContexts()
578
579
Tor Norbye3a2425a2013-11-04 10:16:08 -0800580 def processNetCommand(self, cmd_id, seq, text):
581 '''Processes a command received from the Java side
582
583 @param cmd_id: the id of the command
584 @param seq: the sequence of the command
585 @param text: the text received in the command
586
587 @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for
588 a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed
589 that the gains from having a fast access to what should be executed are lost because of the function call in
590 a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices
591 makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time,
592 it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
593 probably will give better performance).
594 '''
Tor Norbye1aa2e092014-08-20 17:01:23 -0700595 #print ID_TO_MEANING[str(cmd_id)], repr(text)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800596
597 self._main_lock.acquire()
598 try:
599 try:
600 cmd = None
601 if cmd_id == CMD_RUN:
602 self.readyToRun = True
603
604 elif cmd_id == CMD_VERSION:
605 # response is version number
Tor Norbye1aa2e092014-08-20 17:01:23 -0700606 # ide_os should be 'WINDOWS' or 'UNIX'.
607 ide_os = 'WINDOWS'
Tor Norbye3a2425a2013-11-04 10:16:08 -0800608
Tor Norbye1aa2e092014-08-20 17:01:23 -0700609 # Breakpoints can be grouped by 'LINE' or by 'ID'.
610 breakpoints_by = 'LINE'
611
612 splitted = text.split('\t')
613 if len(splitted) == 1:
614 _local_version = splitted
615
616 elif len(splitted) == 2:
617 _local_version, ide_os = splitted
618
619 elif len(splitted) == 3:
620 _local_version, ide_os, breakpoints_by = splitted
621
622 if breakpoints_by == 'ID':
623 self._set_breakpoints_with_id = True
624 else:
625 self._set_breakpoints_with_id = False
626
627 pydevd_file_utils.set_ide_os(ide_os)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800628
629 cmd = self.cmdFactory.makeVersionMessage(seq)
630
631 elif cmd_id == CMD_LIST_THREADS:
632 # response is a list of threads
633 cmd = self.cmdFactory.makeListThreadsMessage(seq)
634
635 elif cmd_id == CMD_THREAD_KILL:
636 int_cmd = InternalTerminateThread(text)
637 self.postInternalCommand(int_cmd, text)
638
639 elif cmd_id == CMD_THREAD_SUSPEND:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700640 # Yes, thread suspend is still done at this point, not through an internal command!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800641 t = PydevdFindThreadById(text)
642 if t:
643 additionalInfo = None
644 try:
645 additionalInfo = t.additionalInfo
646 except AttributeError:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700647 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800648
649 if additionalInfo is not None:
650 for frame in additionalInfo.IterFrames():
651 self.SetTraceForFrameAndParents(frame)
652 del frame
653
654 self.setSuspend(t, CMD_THREAD_SUSPEND)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700655 elif text.startswith('__frame__:'):
656 sys.stderr.write("Can't suspend tasklet: %s\n" % (text,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800657
658 elif cmd_id == CMD_THREAD_RUN:
659 t = PydevdFindThreadById(text)
660 if t:
661 thread_id = GetThreadId(t)
662 int_cmd = InternalRunThread(thread_id)
663 self.postInternalCommand(int_cmd, thread_id)
664
Tor Norbyec667c1f2014-05-28 17:06:51 -0700665 elif text.startswith('__frame__:'):
666 sys.stderr.write("Can't make tasklet run: %s\n" % (text,))
667
668
Tor Norbye3a2425a2013-11-04 10:16:08 -0800669 elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700670 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800671 t = PydevdFindThreadById(text)
672 if t:
673 thread_id = GetThreadId(t)
674 int_cmd = InternalStepThread(thread_id, cmd_id)
675 self.postInternalCommand(int_cmd, thread_id)
676
Tor Norbyec667c1f2014-05-28 17:06:51 -0700677 elif text.startswith('__frame__:'):
678 sys.stderr.write("Can't make tasklet step command: %s\n" % (text,))
679
680
Tor Norbye3a2425a2013-11-04 10:16:08 -0800681 elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700682 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800683 thread_id, line, func_name = text.split('\t', 2)
684 t = PydevdFindThreadById(thread_id)
685 if t:
686 int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name)
687 self.postInternalCommand(int_cmd, thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700688 elif thread_id.startswith('__frame__:'):
689 sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800690
691
692 elif cmd_id == CMD_RELOAD_CODE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700693 # we received some command to make a reload of a module
Tor Norbye3a2425a2013-11-04 10:16:08 -0800694 module_name = text.strip()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800695
Tor Norbyec667c1f2014-05-28 17:06:51 -0700696 thread_id = '*' # Any thread
Tor Norbye3a2425a2013-11-04 10:16:08 -0800697
Tor Norbyec667c1f2014-05-28 17:06:51 -0700698 # Note: not going for the main thread because in this case it'd only do the load
699 # when we stopped on a breakpoint.
700 # for tid, t in self._running_thread_ids.items(): #Iterate in copy
701 # thread_name = t.getName()
702 #
703 # print thread_name, GetThreadId(t)
704 # #Note: if possible, try to reload on the main thread
705 # if thread_name == 'MainThread':
706 # thread_id = tid
707
708 int_cmd = ReloadCodeCommand(module_name, thread_id)
709 self.postInternalCommand(int_cmd, thread_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800710
711
712 elif cmd_id == CMD_CHANGE_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700713 # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change
Tor Norbye3a2425a2013-11-04 10:16:08 -0800714 try:
715 thread_id, frame_id, scope, attr_and_value = text.split('\t', 3)
716
717 tab_index = attr_and_value.rindex('\t')
718 attr = attr_and_value[0:tab_index].replace('\t', '.')
719 value = attr_and_value[tab_index + 1:]
720 int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value)
721 self.postInternalCommand(int_cmd, thread_id)
722
723 except:
724 traceback.print_exc()
725
726 elif cmd_id == CMD_GET_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700727 # we received some command to get a variable
728 # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes*
Tor Norbye3a2425a2013-11-04 10:16:08 -0800729 try:
730 thread_id, frame_id, scopeattrs = text.split('\t', 2)
731
Tor Norbyec667c1f2014-05-28 17:06:51 -0700732 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
Tor Norbye3a2425a2013-11-04 10:16:08 -0800733 scope, attrs = scopeattrs.split('\t', 1)
734 else:
735 scope, attrs = (scopeattrs, None)
736
737 int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs)
738 self.postInternalCommand(int_cmd, thread_id)
739
740 except:
741 traceback.print_exc()
742
743 elif cmd_id == CMD_GET_COMPLETIONS:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700744 # we received some command to get a variable
745 # the text is: thread_id\tframe_id\tactivation token
Tor Norbye3a2425a2013-11-04 10:16:08 -0800746 try:
747 thread_id, frame_id, scope, act_tok = text.split('\t', 3)
748
749 int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok)
750 self.postInternalCommand(int_cmd, thread_id)
751
752 except:
753 traceback.print_exc()
754
755 elif cmd_id == CMD_GET_FRAME:
756 thread_id, frame_id, scope = text.split('\t', 2)
757
758 int_cmd = InternalGetFrame(seq, thread_id, frame_id)
759 self.postInternalCommand(int_cmd, thread_id)
760
761 elif cmd_id == CMD_SET_BREAK:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700762 # func name: 'None': match anything. Empty: match global, specified: only method context.
Tor Norbyec667c1f2014-05-28 17:06:51 -0700763 # command to add some breakpoint.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800764 # text is file\tline. Add to breakpoints dictionary
Tor Norbye1aa2e092014-08-20 17:01:23 -0700765 if self._set_breakpoints_with_id:
766 breakpoint_id, type, file, line, func_name, condition, expression = text.split('\t', 6)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800767
Tor Norbye1aa2e092014-08-20 17:01:23 -0700768 breakpoint_id = int(breakpoint_id)
769 line = int(line)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800770
Tor Norbyec667c1f2014-05-28 17:06:51 -0700771 # We must restore new lines and tabs as done in
772 # AbstractDebugTarget.breakpointAdded
Tor Norbye3a2425a2013-11-04 10:16:08 -0800773 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
774 replace("@_@TAB_CHAR@_@", '\t').strip()
775
Tor Norbye1aa2e092014-08-20 17:01:23 -0700776 expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\
777 replace("@_@TAB_CHAR@_@", '\t').strip()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800778 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700779 #Note: this else should be removed after PyCharm migrates to setting
780 #breakpoints by id (and ideally also provides func_name).
781 type, file, line, condition, expression = text.split('\t', 4)
782 # If we don't have an id given for each breakpoint, consider
783 # the id to be the line.
784 breakpoint_id = line = int(line)
785 if condition.startswith('**FUNC**'):
786 func_name, condition = condition.split('\t', 1)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800787
Tor Norbye1aa2e092014-08-20 17:01:23 -0700788 # We must restore new lines and tabs as done in
789 # AbstractDebugTarget.breakpointAdded
790 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
791 replace("@_@TAB_CHAR@_@", '\t').strip()
792
793 func_name = func_name[8:]
794 else:
795 func_name = 'None' # Match anything if not specified.
796
797 if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
798 file = file.encode(file_system_encoding)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800799
800 file = NormFileToServer(file)
801
802 if not pydevd_file_utils.exists(file):
803 sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
804 ' to file that does not exist: %s (will have no effect)\n' % (file,))
805 sys.stderr.flush()
806
Tor Norbye3a2425a2013-11-04 10:16:08 -0800807
808 if len(condition) <= 0 or condition is None or condition == "None":
809 condition = None
810
811 if len(expression) <= 0 or expression is None or expression == "None":
812 expression = None
813
814 if type == 'python-line':
Tor Norbye1aa2e092014-08-20 17:01:23 -0700815 breakpoint = LineBreakpoint(line, condition, func_name, expression)
816 breakpoints = self.breakpoints
817 file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
Tor Norbye3a2425a2013-11-04 10:16:08 -0800818 elif type == 'django-line':
Tor Norbye1aa2e092014-08-20 17:01:23 -0700819 breakpoint = DjangoLineBreakpoint(file, line, condition, func_name, expression)
820 breakpoints = self.django_breakpoints
821 file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
Tor Norbye3a2425a2013-11-04 10:16:08 -0800822 else:
823 raise NameError(type)
824
Tor Norbye1aa2e092014-08-20 17:01:23 -0700825 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
826 pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8')))
827 sys.stderr.flush()
828
829 if DictContains(file_to_id_to_breakpoint, file):
830 id_to_pybreakpoint = file_to_id_to_breakpoint[file]
831 else:
832 id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {}
833
834 id_to_pybreakpoint[breakpoint_id] = breakpoint
835 self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
836
Tor Norbye3a2425a2013-11-04 10:16:08 -0800837 self.setTracingForUntracedContexts()
838
839 elif cmd_id == CMD_REMOVE_BREAK:
840 #command to remove some breakpoint
Tor Norbye1aa2e092014-08-20 17:01:23 -0700841 #text is type\file\tid. Remove from breakpoints dictionary
842 breakpoint_type, file, breakpoint_id = text.split('\t', 2)
843
844 if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
845 file = file.encode(file_system_encoding)
846
Tor Norbye3a2425a2013-11-04 10:16:08 -0800847 file = NormFileToServer(file)
Tor Norbye1aa2e092014-08-20 17:01:23 -0700848
Tor Norbye3a2425a2013-11-04 10:16:08 -0800849 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700850 breakpoint_id = int(breakpoint_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800851 except ValueError:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700852 pydev_log.error('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800853
854 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700855 if breakpoint_type == 'python-line':
856 breakpoints = self.breakpoints
857 file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
858 elif breakpoint_type == 'django-line':
859 breakpoints = self.django_breakpoints
860 file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
861 else:
862 raise NameError(breakpoint_type)
863
Tor Norbye3a2425a2013-11-04 10:16:08 -0800864 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700865 id_to_pybreakpoint = file_to_id_to_breakpoint[file]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800866 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700867 existing = id_to_pybreakpoint[breakpoint_id]
868 sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (
869 file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id))
870
871 del id_to_pybreakpoint[breakpoint_id]
872 self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800873 except KeyError:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700874 pydev_log.error("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (
875 file, breakpoint_id, DictKeys(id_to_pybreakpoint)))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800876
Tor Norbye3a2425a2013-11-04 10:16:08 -0800877
878 elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
879 #command to evaluate the given expression
880 #text is: thread\tstackframe\tLOCAL\texpression
881 thread_id, frame_id, scope, expression, trim = text.split('\t', 4)
882 int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression,
883 cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1)
884 self.postInternalCommand(int_cmd, thread_id)
885
886 elif cmd_id == CMD_CONSOLE_EXEC:
887 #command to exec expression in console, in case expression is only partially valid 'False' is returned
888 #text is: thread\tstackframe\tLOCAL\texpression
889
890 thread_id, frame_id, scope, expression = text.split('\t', 3)
891
892 int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
893 self.postInternalCommand(int_cmd, thread_id)
894
Tor Norbye1aa2e092014-08-20 17:01:23 -0700895 elif cmd_id == CMD_SET_PY_EXCEPTION:
896 # Command which receives set of exceptions on which user wants to break the debugger
897 # text is: break_on_uncaught;break_on_caught;TypeError;ImportError;zipimport.ZipImportError;
898 # This API is optional and works 'in bulk' -- it's possible
899 # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK
900 # which allows setting caught/uncaught per exception.
901 #
902 splitted = text.split(';')
903 self.break_on_uncaught_exceptions = {}
904 self.break_on_caught_exceptions = {}
905 added = []
906 if len(splitted) >= 4:
907 if splitted[0] == 'true':
908 break_on_uncaught = True
909 else:
910 break_on_uncaught = False
911
912 if splitted[1] == 'true':
913 break_on_caught = True
914 else:
915 break_on_caught = False
916
917 if splitted[2] == 'true':
918 self.break_on_exceptions_thrown_in_same_context = True
919 else:
920 self.break_on_exceptions_thrown_in_same_context = False
921
922 if splitted[3] == 'true':
923 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
924 else:
925 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = False
926
927 for exception_type in splitted[4:]:
928 exception_type = exception_type.strip()
929 if not exception_type:
930 continue
931
932 exception_breakpoint = self.add_break_on_exception(
933 exception_type,
934 notify_always=break_on_caught,
935 notify_on_terminate=break_on_uncaught,
936 notify_on_first_raise_only=False,
937 )
938 added.append(exception_breakpoint)
939
940 self.update_after_exceptions_added(added)
941
942 else:
943 sys.stderr.write("Error when setting exception list. Received: %s\n" % (text,))
944
945 elif cmd_id == CMD_GET_FILE_CONTENTS:
946
947 if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
948 text = text.encode(file_system_encoding)
949
950 if os.path.exists(text):
951 f = open(text, 'r')
952 try:
953 source = f.read()
954 finally:
955 f.close()
956 cmd = self.cmdFactory.makeGetFileContents(seq, source)
957
958 elif cmd_id == CMD_SET_PROPERTY_TRACE:
959 # Command which receives whether to trace property getter/setter/deleter
960 # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter
961 if text != "":
962 splitted = text.split(';')
963 if len(splitted) >= 3:
964 if self.disable_property_trace is False and splitted[0] == 'true':
965 # Replacing property by custom property only when the debugger starts
966 pydevd_traceproperty.replace_builtin_property()
967 self.disable_property_trace = True
968 # Enable/Disable tracing of the property getter
969 if splitted[1] == 'true':
970 self.disable_property_getter_trace = True
971 else:
972 self.disable_property_getter_trace = False
973 # Enable/Disable tracing of the property setter
974 if splitted[2] == 'true':
975 self.disable_property_setter_trace = True
976 else:
977 self.disable_property_setter_trace = False
978 # Enable/Disable tracing of the property deleter
979 if splitted[3] == 'true':
980 self.disable_property_deleter_trace = True
981 else:
982 self.disable_property_deleter_trace = False
983 else:
984 # User hasn't configured any settings for property tracing
985 pass
986
Tor Norbye3a2425a2013-11-04 10:16:08 -0800987 elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
988 exception, notify_always, notify_on_terminate = text.split('\t', 2)
Tor Norbye1aa2e092014-08-20 17:01:23 -0700989 exception_breakpoint = self.add_break_on_exception(
990 exception,
991 notify_always=int(notify_always) > 0,
992 notify_on_terminate = int(notify_on_terminate) == 1,
993 notify_on_first_raise_only=int(notify_always) == 2
994 )
995 self.update_after_exceptions_added([exception_breakpoint])
Tor Norbye3a2425a2013-11-04 10:16:08 -0800996
997 elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
998 exception = text
999 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001000 cp = self.break_on_uncaught_exceptions.copy()
1001 DictPop(cp, exception, None)
1002 self.break_on_uncaught_exceptions = cp
1003
1004 cp = self.break_on_caught_exceptions.copy()
1005 DictPop(cp, exception, None)
1006 self.break_on_caught_exceptions = cp
Tor Norbye3a2425a2013-11-04 10:16:08 -08001007 except:
Tor Norbye65f60eb2014-07-16 18:07:37 -07001008 pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]);
Tor Norbye3a2425a2013-11-04 10:16:08 -08001009 update_exception_hook(self)
1010
1011 elif cmd_id == CMD_LOAD_SOURCE:
1012 path = text
1013 try:
1014 f = open(path, 'r')
1015 source = f.read()
1016 self.cmdFactory.makeLoadSourceMessage(seq, source, self)
1017 except:
1018 return self.cmdFactory.makeErrorMessage(seq, pydevd_tracing.GetExceptionTracebackStr())
1019
1020 elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK:
1021 exception = text
1022
1023 self.django_exception_break[exception] = True
1024 self.setTracingForUntracedContexts()
1025
1026 elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
1027 exception = text
1028
1029 try:
1030 del self.django_exception_break[exception]
1031 except :
1032 pass
1033
Tor Norbye1aa2e092014-08-20 17:01:23 -07001034 elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
1035 # Command which takes care for the debug console communication
1036 if text != "":
1037 thread_id, frame_id, console_command = text.split('\t', 2)
1038 console_command, line = console_command.split('\t')
1039 if console_command == 'EVALUATE':
1040 int_cmd = InternalEvaluateConsoleExpression(seq, thread_id, frame_id, line)
1041 elif console_command == 'GET_COMPLETIONS':
1042 int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line)
1043 self.postInternalCommand(int_cmd, thread_id)
1044
1045 elif cmd_id == CMD_RUN_CUSTOM_OPERATION:
1046 # Command which runs a custom operation
1047 if text != "":
1048 try:
1049 location, custom = text.split('||', 1)
1050 except:
1051 sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,))
1052 raise
1053
1054 thread_id, frame_id, scopeattrs = location.split('\t', 2)
1055
1056 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
1057 scope, attrs = scopeattrs.split('\t', 1)
1058 else:
1059 scope, attrs = (scopeattrs, None)
1060
1061 # : style: EXECFILE or EXEC
1062 # : encoded_code_or_file: file to execute or code
1063 # : fname: name of function to be executed in the resulting namespace
1064 style, encoded_code_or_file, fnname = custom.split('\t', 3)
1065 int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs,
1066 style, encoded_code_or_file, fnname)
1067 self.postInternalCommand(int_cmd, thread_id)
1068
1069 elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT:
1070 if text:
1071 replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround.
1072 if not IS_PY3K:
1073 replace = unicode(replace)
1074
1075 if text.startswith(replace):
1076 text = text[8:]
1077 self.filename_to_lines_where_exceptions_are_ignored.clear()
1078
1079 if text:
1080 for line in text.split('||'): # Can be bulk-created (one in each line)
1081 filename, line_number = line.split('|')
1082 if not IS_PY3K:
1083 filename = filename.encode(file_system_encoding)
1084
1085 filename = NormFileToServer(filename)
1086
1087 if os.path.exists(filename):
1088 lines_ignored = self.filename_to_lines_where_exceptions_are_ignored.get(filename)
1089 if lines_ignored is None:
1090 lines_ignored = self.filename_to_lines_where_exceptions_are_ignored[filename] = {}
1091 lines_ignored[int(line_number)] = 1
1092 else:
1093 sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\
1094 ' on file that does not exist: %s (will have no effect)\n' % (filename,))
1095
1096 elif cmd_id == CMD_ENABLE_DONT_TRACE:
1097 if text:
1098 true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround.
1099 if not IS_PY3K:
1100 true_str = unicode(true_str)
1101
1102 mode = text.strip() == true_str
1103 pydevd_dont_trace.trace_filter(mode)
1104
Tor Norbye3a2425a2013-11-04 10:16:08 -08001105 else:
1106 #I have no idea what this is all about
1107 cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))
1108
1109 if cmd is not None:
1110 self.writer.addCommand(cmd)
1111 del cmd
1112
1113 except Exception:
1114 traceback.print_exc()
1115 cmd = self.cmdFactory.makeErrorMessage(seq,
1116 "Unexpected exception in processNetCommand.\nInitial params: %s" % ((cmd_id, seq, text),))
1117
1118 self.writer.addCommand(cmd)
1119 finally:
1120 self._main_lock.release()
1121
1122 def processThreadNotAlive(self, threadId):
1123 """ if thread is not alive, cancel trace_dispatch processing """
1124 self._lock_running_thread_ids.acquire()
1125 try:
1126 thread = self._running_thread_ids.pop(threadId, None)
1127 if thread is None:
1128 return
1129
1130 wasNotified = thread.additionalInfo.pydev_notify_kill
1131 if not wasNotified:
1132 thread.additionalInfo.pydev_notify_kill = True
1133
1134 finally:
1135 self._lock_running_thread_ids.release()
1136
1137 cmd = self.cmdFactory.makeThreadKilledMessage(threadId)
1138 self.writer.addCommand(cmd)
1139
1140
1141 def setSuspend(self, thread, stop_reason):
1142 thread.additionalInfo.suspend_type = PYTHON_SUSPEND
1143 thread.additionalInfo.pydev_state = STATE_SUSPEND
1144 thread.stop_reason = stop_reason
1145
Tor Norbye1aa2e092014-08-20 17:01:23 -07001146 # If conditional breakpoint raises any exception during evaluation send details to Java
1147 if stop_reason == CMD_SET_BREAK and self.suspend_on_breakpoint_exception:
1148 self.sendBreakpointConditionException(thread)
1149
1150
1151 def sendBreakpointConditionException(self, thread):
1152 """If conditional breakpoint raises an exception during evaluation
1153 send exception details to java
1154 """
1155 thread_id = GetThreadId(thread)
1156 conditional_breakpoint_exception_tuple = thread.additionalInfo.conditional_breakpoint_exception
1157 # conditional_breakpoint_exception_tuple - should contain 2 values (exception_type, stacktrace)
1158 if conditional_breakpoint_exception_tuple and len(conditional_breakpoint_exception_tuple) == 2:
1159 exc_type, stacktrace = conditional_breakpoint_exception_tuple
1160 int_cmd = InternalGetBreakpointException(thread_id, exc_type, stacktrace)
1161 # Reset the conditional_breakpoint_exception details to None
1162 thread.additionalInfo.conditional_breakpoint_exception = None
1163 self.postInternalCommand(int_cmd, thread_id)
1164
1165
1166 def sendCaughtExceptionStack(self, thread, arg, curr_frame_id):
1167 """Sends details on the exception which was caught (and where we stopped) to the java side.
1168
1169 arg is: exception type, description, traceback object
1170 """
1171 thread_id = GetThreadId(thread)
1172 int_cmd = InternalSendCurrExceptionTrace(thread_id, arg, curr_frame_id)
1173 self.postInternalCommand(int_cmd, thread_id)
1174
1175
1176 def sendCaughtExceptionStackProceeded(self, thread):
1177 """Sends that some thread was resumed and is no longer showing an exception trace.
1178 """
1179 thread_id = GetThreadId(thread)
1180 int_cmd = InternalSendCurrExceptionTraceProceeded(thread_id)
1181 self.postInternalCommand(int_cmd, thread_id)
1182 self.processInternalCommands()
1183
Tor Norbye3a2425a2013-11-04 10:16:08 -08001184
1185 def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
1186 """ busy waits until the thread state changes to RUN
1187 it expects thread's state as attributes of the thread.
1188 Upon running, processes any outstanding Stepping commands.
1189 """
1190 self.processInternalCommands()
1191
1192 message = getattr(thread.additionalInfo, "message", None)
1193
1194 cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message)
1195 self.writer.addCommand(cmd)
1196
Tor Norbyec667c1f2014-05-28 17:06:51 -07001197 CustomFramesContainer.custom_frames_lock.acquire()
1198 try:
1199 from_this_thread = []
Tor Norbye3a2425a2013-11-04 10:16:08 -08001200
Tor Norbye1aa2e092014-08-20 17:01:23 -07001201 for frame_id, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
Tor Norbyec667c1f2014-05-28 17:06:51 -07001202 if custom_frame.thread_id == thread.ident:
1203 # print >> sys.stderr, 'Frame created: ', frame_id
1204 self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
1205 self.writer.addCommand(self.cmdFactory.makeThreadSuspendMessage(frame_id, custom_frame.frame, CMD_THREAD_SUSPEND, ""))
1206
1207 from_this_thread.append(frame_id)
1208
1209 finally:
1210 CustomFramesContainer.custom_frames_lock.release()
1211
1212
1213
1214 info = thread.additionalInfo
Tor Norbye3a2425a2013-11-04 10:16:08 -08001215 while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
1216 self.processInternalCommands()
1217 time.sleep(0.01)
1218
Tor Norbyec667c1f2014-05-28 17:06:51 -07001219 # process any stepping instructions
Tor Norbye3a2425a2013-11-04 10:16:08 -08001220 if info.pydev_step_cmd == CMD_STEP_INTO:
1221 info.pydev_step_stop = None
1222 info.pydev_smart_step_stop = None
1223
1224 elif info.pydev_step_cmd == CMD_STEP_OVER:
1225 info.pydev_step_stop = frame
1226 info.pydev_smart_step_stop = None
1227 self.SetTraceForFrameAndParents(frame)
1228
1229 elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
1230 self.SetTraceForFrameAndParents(frame)
1231 info.pydev_step_stop = None
1232 info.pydev_smart_step_stop = frame
1233
1234 elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT :
1235 self.SetTraceForFrameAndParents(frame)
1236
1237 if event == 'line' or event == 'exception':
1238 #If we're already in the correct context, we have to stop it now, because we can act only on
1239 #line events -- if a return was the next statement it wouldn't work (so, we have this code
1240 #repeated at pydevd_frame).
1241 stop = False
1242 curr_func_name = frame.f_code.co_name
1243
1244 #global context is set with an empty name
1245 if curr_func_name in ('?', '<module>'):
1246 curr_func_name = ''
1247
1248 if curr_func_name == info.pydev_func_name:
1249 line = info.pydev_next_line
1250 if frame.f_lineno == line:
1251 stop = True
1252 else :
1253 if frame.f_trace is None:
1254 frame.f_trace = self.trace_dispatch
1255 frame.f_lineno = line
1256 frame.f_trace = None
1257 stop = True
1258 if stop:
1259 info.pydev_state = STATE_SUSPEND
1260 self.doWaitSuspend(thread, frame, event, arg)
1261 return
1262
1263
1264 elif info.pydev_step_cmd == CMD_STEP_RETURN:
1265 back_frame = frame.f_back
1266 if back_frame is not None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001267 # steps back to the same frame (in a return call it will stop in the 'back frame' for the user)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001268 info.pydev_step_stop = frame
1269 self.SetTraceForFrameAndParents(frame)
1270 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001271 # No back frame?!? -- this happens in jython when we have some frame created from an awt event
1272 # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java')
1273 # so, if we're doing a step return in this situation, it's the same as just making it run
Tor Norbye3a2425a2013-11-04 10:16:08 -08001274 info.pydev_step_stop = None
1275 info.pydev_step_cmd = None
1276 info.pydev_state = STATE_RUN
1277
1278 del frame
1279 cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd)
1280 self.writer.addCommand(cmd)
1281
Tor Norbyec667c1f2014-05-28 17:06:51 -07001282 CustomFramesContainer.custom_frames_lock.acquire()
1283 try:
1284 # The ones that remained on last_running must now be removed.
1285 for frame_id in from_this_thread:
1286 # print >> sys.stderr, 'Removing created frame: ', frame_id
1287 self.writer.addCommand(self.cmdFactory.makeThreadKilledMessage(frame_id))
1288
1289 finally:
1290 CustomFramesContainer.custom_frames_lock.release()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001291
1292 def handle_post_mortem_stop(self, additionalInfo, t):
1293 pydev_log.debug("We are stopping in post-mortem\n")
Tor Norbye3a2425a2013-11-04 10:16:08 -08001294 frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
1295 thread_id = GetThreadId(t)
1296 pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
1297 try:
1298 try:
1299 add_exception_to_frame(frame, additionalInfo.exception)
1300 self.setSuspend(t, CMD_ADD_EXCEPTION_BREAK)
1301 self.doWaitSuspend(t, frame, 'exception', None)
1302 except:
1303 pydev_log.error("We've got an error while stopping in post-mortem: %s\n"%sys.exc_info()[0])
1304 finally:
1305 additionalInfo.pydev_force_stop_at_exception = None
1306 pydevd_vars.removeAdditionalFrameById(thread_id)
1307
1308 def trace_dispatch(self, frame, event, arg):
1309 ''' This is the callback used when we enter some context in the debugger.
1310
1311 We also decorate the thread we are in with info about the debugging.
1312 The attributes added are:
1313 pydev_state
1314 pydev_step_stop
1315 pydev_step_cmd
1316 pydev_notify_kill
1317 '''
1318 try:
1319 if self._finishDebuggingSession and not self._terminationEventSent:
1320 #that was not working very well because jython gave some socket errors
Tor Norbye3a2425a2013-11-04 10:16:08 -08001321 try:
1322 threads = threadingEnumerate()
1323 for t in threads:
1324 if hasattr(t, 'doKillPydevThread'):
1325 t.doKillPydevThread()
1326 except:
1327 traceback.print_exc()
1328 self._terminationEventSent = True
1329 return None
1330
1331 filename, base = GetFilenameAndBase(frame)
1332
1333 is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd
1334
1335 if is_file_to_ignore:
1336 return None
1337
1338 #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name)
1339 try:
1340 #this shouldn't give an exception, but it could happen... (python bug)
1341 #see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
1342 #and related bug: http://bugs.python.org/issue1733757
1343 t = threadingCurrentThread()
1344 except:
1345 frame.f_trace = self.trace_dispatch
1346 return self.trace_dispatch
1347
1348 try:
1349 additionalInfo = t.additionalInfo
1350 if additionalInfo is None:
1351 raise AttributeError()
1352 except:
1353 t.additionalInfo = PyDBAdditionalThreadInfo()
1354 additionalInfo = t.additionalInfo
1355
1356 if additionalInfo is None:
1357 return None
1358
1359 if additionalInfo.is_tracing:
1360 f = frame
1361 while f is not None:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001362 if 'trace_dispatch' == f.f_code.co_name:
1363 _fname, bs = GetFilenameAndBase(f)
1364 if bs == 'pydevd_frame.py':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001365 return None #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
1366 f = f.f_back
1367
1368 # if thread is not alive, cancel trace_dispatch processing
Tor Norbye92584642014-04-17 08:39:25 -07001369 if not isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001370 self.processThreadNotAlive(GetThreadId(t))
Tor Norbye92584642014-04-17 08:39:25 -07001371 return None # suspend tracing
Tor Norbye3a2425a2013-11-04 10:16:08 -08001372
Tor Norbyec667c1f2014-05-28 17:06:51 -07001373 # each new frame...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001374 return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
1375
1376 except SystemExit:
1377 return None
1378
Tor Norbye3a2425a2013-11-04 10:16:08 -08001379 except Exception:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001380 # Log it
Tor Norbye3a2425a2013-11-04 10:16:08 -08001381 if traceback is not None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001382 # This can actually happen during the interpreter shutdown in Python 2.7
Tor Norbye3a2425a2013-11-04 10:16:08 -08001383 traceback.print_exc()
1384 return None
1385
1386 if USE_PSYCO_OPTIMIZATION:
1387 try:
1388 import psyco
1389 trace_dispatch = psyco.proxy(trace_dispatch)
1390 processNetCommand = psyco.proxy(processNetCommand)
1391 processInternalCommands = psyco.proxy(processInternalCommands)
1392 doWaitSuspend = psyco.proxy(doWaitSuspend)
1393 getInternalQueue = psyco.proxy(getInternalQueue)
1394 except ImportError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001395 if hasattr(sys, 'exc_clear'): # jython does not have it
1396 sys.exc_clear() # don't keep the traceback (let's keep it clear for when we go to the point of executing client code)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001397
1398 if not IS_PY3K and not IS_PY27 and not IS_64_BITS and not sys.platform.startswith("java") and not sys.platform.startswith("cli"):
1399 sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
1400 sys.stderr.flush()
1401
1402
1403
Tor Norbyec667c1f2014-05-28 17:06:51 -07001404 def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001405 dispatch_func = self.trace_dispatch
1406
1407 if also_add_to_passed_frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001408 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001409
1410 frame = frame.f_back
1411 while frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001412 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001413
1414 frame = frame.f_back
1415 del frame
1416
1417 def update_trace(self, frame, dispatch_func, overwrite_prev):
1418 if frame.f_trace is None:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001419 frame.f_trace = dispatch_func
Tor Norbye3a2425a2013-11-04 10:16:08 -08001420 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001421 if overwrite_prev:
1422 frame.f_trace = dispatch_func
1423 else:
1424 try:
1425 #If it's the trace_exception, go back to the frame trace dispatch!
1426 if frame.f_trace.im_func.__name__ == 'trace_exception':
1427 frame.f_trace = frame.f_trace.im_self.trace_dispatch
1428 except AttributeError:
1429 pass
1430 frame = frame.f_back
Tor Norbye3a2425a2013-11-04 10:16:08 -08001431 del frame
1432
Tor Norbyec667c1f2014-05-28 17:06:51 -07001433 def prepareToRun(self):
1434 ''' Shared code to prepare debugging by installing traces and registering threads '''
1435
1436 # for completeness, we'll register the pydevd.reader & pydevd.writer threads
1437 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1438 self.writer.addCommand(net)
1439 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1440 self.writer.addCommand(net)
1441
1442 pydevd_tracing.SetTrace(self.trace_dispatch)
1443 self.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001444
1445
Tor Norbyec667c1f2014-05-28 17:06:51 -07001446 PyDBCommandThread(self).start()
1447 PyDBCheckAliveThread(self).start()
1448
Tor Norbye1aa2e092014-08-20 17:01:23 -07001449
Tor Norbyec667c1f2014-05-28 17:06:51 -07001450 def patch_threads(self):
1451 try:
1452 # not available in jython!
1453 threading.settrace(self.trace_dispatch) # for all future threads
1454 except:
1455 pass
1456
Tor Norbye1aa2e092014-08-20 17:01:23 -07001457 from pydev_monkey import patch_thread_modules
1458 patch_thread_modules()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001459
1460
1461 def run(self, file, globals=None, locals=None, set_trace=True):
1462 if os.path.isdir(file):
1463 new_target = os.path.join(file, '__main__.py')
1464 if os.path.isfile(new_target):
1465 file = new_target
Tor Norbye3a2425a2013-11-04 10:16:08 -08001466
1467 if globals is None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001468 # patch provided by: Scott Schlesier - when script is run, it does not
1469 # use globals from pydevd:
1470 # This will prevent the pydevd script from contaminating the namespace for the script to be debugged
Tor Norbye3a2425a2013-11-04 10:16:08 -08001471
Tor Norbyec667c1f2014-05-28 17:06:51 -07001472 # pretend pydevd is not the main module, and
1473 # convince the file to be debugged that it was loaded as main
Tor Norbye3a2425a2013-11-04 10:16:08 -08001474 sys.modules['pydevd'] = sys.modules['__main__']
1475 sys.modules['pydevd'].__name__ = 'pydevd'
1476
1477 from imp import new_module
1478 m = new_module('__main__')
1479 sys.modules['__main__'] = m
Tor Norbye70ae6f22014-02-06 14:02:54 -08001480 if hasattr(sys.modules['pydevd'], '__loader__'):
1481 setattr(m, '__loader__', getattr(sys.modules['pydevd'], '__loader__'))
Tor Norbye1aa2e092014-08-20 17:01:23 -07001482
Tor Norbye3a2425a2013-11-04 10:16:08 -08001483 m.__file__ = file
1484 globals = m.__dict__
1485 try:
1486 globals['__builtins__'] = __builtins__
1487 except NameError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001488 pass # Not there on Jython...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001489
1490 if locals is None:
1491 locals = globals
1492
Tor Norbyec667c1f2014-05-28 17:06:51 -07001493 if set_trace:
1494 # Predefined (writable) attributes: __name__ is the module's name;
1495 # __doc__ is the module's documentation string, or None if unavailable;
1496 # __file__ is the pathname of the file from which the module was loaded,
1497 # if it was loaded from a file. The __file__ attribute is not present for
1498 # C modules that are statically linked into the interpreter; for extension modules
1499 # loaded dynamically from a shared library, it is the pathname of the shared library file.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001500
1501
Tor Norbyec667c1f2014-05-28 17:06:51 -07001502 # I think this is an ugly hack, bug it works (seems to) for the bug that says that sys.path should be the same in
1503 # debug and run.
1504 if m.__file__.startswith(sys.path[0]):
1505 # print >> sys.stderr, 'Deleting: ', sys.path[0]
1506 del sys.path[0]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001507
Tor Norbyec667c1f2014-05-28 17:06:51 -07001508 # now, the local directory has to be added to the pythonpath
1509 # sys.path.insert(0, os.getcwd())
1510 # Changed: it's not the local directory, but the directory of the file launched
1511 # The file being run ust be in the pythonpath (even if it was not before)
1512 sys.path.insert(0, os.path.split(file)[0])
Tor Norbye3a2425a2013-11-04 10:16:08 -08001513
Tor Norbyec667c1f2014-05-28 17:06:51 -07001514 self.prepareToRun()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001515
Tor Norbyec667c1f2014-05-28 17:06:51 -07001516 while not self.readyToRun:
1517 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001518
Tor Norbye3a2425a2013-11-04 10:16:08 -08001519
Tor Norbyec667c1f2014-05-28 17:06:51 -07001520 pydev_imports.execfile(file, globals, locals) # execute the script
Tor Norbye3a2425a2013-11-04 10:16:08 -08001521
1522 def exiting(self):
1523 sys.stdout.flush()
1524 sys.stderr.flush()
1525 self.checkOutputRedirect()
1526 cmd = self.cmdFactory.makeExitMessage()
1527 self.writer.addCommand(cmd)
1528
1529def set_debug(setup):
1530 setup['DEBUG_RECORD_SOCKET_READS'] = True
1531 setup['DEBUG_TRACE_BREAKPOINTS'] = 1
1532 setup['DEBUG_TRACE_LEVEL'] = 3
1533
1534
1535def processCommandLine(argv):
1536 """ parses the arguments.
1537 removes our arguments from the command line """
1538 setup = {}
1539 setup['client'] = ''
1540 setup['server'] = False
1541 setup['port'] = 0
1542 setup['file'] = ''
Tor Norbye1aa2e092014-08-20 17:01:23 -07001543 setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling)
1544 setup['multiprocess'] = False # Used by PyDev (creates new connection to ide)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001545 setup['save-signatures'] = False
1546 i = 0
1547 del argv[0]
1548 while (i < len(argv)):
1549 if (argv[i] == '--port'):
1550 del argv[i]
1551 setup['port'] = int(argv[i])
1552 del argv[i]
1553 elif (argv[i] == '--vm_type'):
1554 del argv[i]
1555 setup['vm_type'] = argv[i]
1556 del argv[i]
1557 elif (argv[i] == '--client'):
1558 del argv[i]
1559 setup['client'] = argv[i]
1560 del argv[i]
1561 elif (argv[i] == '--server'):
1562 del argv[i]
1563 setup['server'] = True
1564 elif (argv[i] == '--file'):
1565 del argv[i]
1566 setup['file'] = argv[i]
1567 i = len(argv) # pop out, file is our last argument
1568 elif (argv[i] == '--DEBUG_RECORD_SOCKET_READS'):
1569 del argv[i]
1570 setup['DEBUG_RECORD_SOCKET_READS'] = True
1571 elif (argv[i] == '--DEBUG'):
1572 del argv[i]
1573 set_debug(setup)
1574 elif (argv[i] == '--multiproc'):
1575 del argv[i]
1576 setup['multiproc'] = True
Tor Norbye1aa2e092014-08-20 17:01:23 -07001577 elif (argv[i] == '--multiprocess'):
1578 del argv[i]
1579 setup['multiprocess'] = True
Tor Norbye3a2425a2013-11-04 10:16:08 -08001580 elif (argv[i] == '--save-signatures'):
1581 del argv[i]
1582 setup['save-signatures'] = True
1583 else:
1584 raise ValueError("unexpected option " + argv[i])
1585 return setup
1586
1587def usage(doExit=0):
1588 sys.stdout.write('Usage:\n')
1589 sys.stdout.write('pydevd.py --port=N [(--client hostname) | --server] --file executable [file_options]\n')
1590 if doExit:
1591 sys.exit(0)
1592
1593def SetTraceForParents(frame, dispatch_func):
1594 frame = frame.f_back
1595 while frame:
1596 if frame.f_trace is None:
1597 frame.f_trace = dispatch_func
1598
1599 frame = frame.f_back
1600 del frame
1601
1602def exit_hook():
1603 debugger = GetGlobalDebugger()
1604 debugger.exiting()
1605
1606def initStdoutRedirect():
1607 if not getattr(sys, 'stdoutBuf', None):
1608 sys.stdoutBuf = pydevd_io.IOBuf()
1609 sys.stdout = pydevd_io.IORedirector(sys.stdout, sys.stdoutBuf) #@UndefinedVariable
1610
1611def initStderrRedirect():
1612 if not getattr(sys, 'stderrBuf', None):
1613 sys.stderrBuf = pydevd_io.IOBuf()
1614 sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable
1615
Tor Norbyec667c1f2014-05-28 17:06:51 -07001616#=======================================================================================================================
1617# settrace
1618#=======================================================================================================================
1619def settrace(
1620 host=None,
1621 stdoutToServer=False,
1622 stderrToServer=False,
1623 port=5678,
1624 suspend=True,
1625 trace_only_current_thread=False,
1626 overwrite_prev_trace=False,
1627 patch_multiprocessing=False,
1628 ):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001629 '''Sets the tracing function with the pydev debug function and initializes needed facilities.
1630
Tor Norbyec667c1f2014-05-28 17:06:51 -07001631 @param host: the user may specify another host, if the debug server is not in the same machine (default is the local
1632 host)
1633
Tor Norbye3a2425a2013-11-04 10:16:08 -08001634 @param stdoutToServer: when this is true, the stdout is passed to the debug server
Tor Norbyec667c1f2014-05-28 17:06:51 -07001635
Tor Norbye3a2425a2013-11-04 10:16:08 -08001636 @param stderrToServer: when this is true, the stderr is passed to the debug server
1637 so that they are printed in its console and not in this process console.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001638
Tor Norbye3a2425a2013-11-04 10:16:08 -08001639 @param port: specifies which port to use for communicating with the server (note that the server must be started
1640 in the same port). @note: currently it's hard-coded at 5678 in the client
Tor Norbyec667c1f2014-05-28 17:06:51 -07001641
Tor Norbye3a2425a2013-11-04 10:16:08 -08001642 @param suspend: whether a breakpoint should be emulated as soon as this function is called.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001643
1644 @param trace_only_current_thread: determines if only the current thread will be traced or all current and future
1645 threads will also have the tracing enabled.
1646
1647 @param overwrite_prev_trace: if True we'll reset the frame.f_trace of frames which are already being traced
1648
1649 @param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched
1650 processes are debugged.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001651 '''
1652 _set_trace_lock.acquire()
1653 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001654 _locked_settrace(
1655 host,
1656 stdoutToServer,
1657 stderrToServer,
1658 port,
1659 suspend,
1660 trace_only_current_thread,
1661 overwrite_prev_trace,
1662 patch_multiprocessing,
1663 )
Tor Norbye3a2425a2013-11-04 10:16:08 -08001664 finally:
1665 _set_trace_lock.release()
1666
Tor Norbyec667c1f2014-05-28 17:06:51 -07001667
1668
Tor Norbye3a2425a2013-11-04 10:16:08 -08001669_set_trace_lock = threading.Lock()
1670
Tor Norbyec667c1f2014-05-28 17:06:51 -07001671def _locked_settrace(
1672 host,
1673 stdoutToServer,
1674 stderrToServer,
1675 port,
1676 suspend,
1677 trace_only_current_thread,
1678 overwrite_prev_trace,
1679 patch_multiprocessing,
1680 ):
1681 if patch_multiprocessing:
1682 try:
1683 import pydev_monkey #Jython 2.1 can't use it...
1684 except:
1685 pass
1686 else:
1687 pydev_monkey.patch_new_process_functions()
1688
Tor Norbye3a2425a2013-11-04 10:16:08 -08001689 if host is None:
1690 import pydev_localhost
1691 host = pydev_localhost.get_localhost()
1692
1693 global connected
1694 global bufferStdOutToServer
1695 global bufferStdErrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001696
1697 if not connected :
Tor Norbye3a2425a2013-11-04 10:16:08 -08001698 pydevd_vm_type.SetupType()
1699
1700 debugger = PyDB()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001701 debugger.connect(host, port) # Note: connect can raise error.
1702
1703 # Mark connected only if it actually succeeded.
1704 connected = True
1705 bufferStdOutToServer = stdoutToServer
1706 bufferStdErrToServer = stderrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001707
1708 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1709 debugger.writer.addCommand(net)
1710 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1711 debugger.writer.addCommand(net)
1712
1713 if bufferStdOutToServer:
1714 initStdoutRedirect()
1715
1716 if bufferStdErrToServer:
1717 initStderrRedirect()
1718
Tor Norbyec667c1f2014-05-28 17:06:51 -07001719 debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev_trace=overwrite_prev_trace)
1720
1721
1722 CustomFramesContainer.custom_frames_lock.acquire()
1723 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001724 for _frameId, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
Tor Norbyec667c1f2014-05-28 17:06:51 -07001725 debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
1726 finally:
1727 CustomFramesContainer.custom_frames_lock.release()
1728
Tor Norbye3a2425a2013-11-04 10:16:08 -08001729
1730 t = threadingCurrentThread()
1731 try:
1732 additionalInfo = t.additionalInfo
1733 except AttributeError:
1734 additionalInfo = PyDBAdditionalThreadInfo()
1735 t.additionalInfo = additionalInfo
1736
1737 while not debugger.readyToRun:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001738 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001739
Tor Norbyec667c1f2014-05-28 17:06:51 -07001740 # note that we do that through pydevd_tracing.SetTrace so that the tracing
1741 # is not warned to the user!
Tor Norbye3a2425a2013-11-04 10:16:08 -08001742 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1743
1744 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001745 # Trace future threads?
1746 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001747
Tor Norbyec667c1f2014-05-28 17:06:51 -07001748 # As this is the first connection, also set tracing for any untraced threads
1749 debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001750
1751 sys.exitfunc = exit_hook
Tor Norbyec667c1f2014-05-28 17:06:51 -07001752 #Suspend as the last thing after all tracing is in place.
1753 if suspend:
1754 debugger.setSuspend(t, CMD_SET_BREAK)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001755
1756 PyDBCommandThread(debugger).start()
1757 PyDBCheckAliveThread(debugger).start()
1758
1759 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001760 # ok, we're already in debug mode, with all set, so, let's just set the break
Tor Norbye3a2425a2013-11-04 10:16:08 -08001761 debugger = GetGlobalDebugger()
1762
1763 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1764
1765 t = threadingCurrentThread()
1766 try:
1767 additionalInfo = t.additionalInfo
1768 except AttributeError:
1769 additionalInfo = PyDBAdditionalThreadInfo()
1770 t.additionalInfo = additionalInfo
1771
1772 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1773
1774 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001775 # Trace future threads?
1776 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001777
Tor Norbye3a2425a2013-11-04 10:16:08 -08001778
1779 if suspend:
1780 debugger.setSuspend(t, CMD_SET_BREAK)
1781
Tor Norbyec667c1f2014-05-28 17:06:51 -07001782
Tor Norbye3a2425a2013-11-04 10:16:08 -08001783def stoptrace():
1784 global connected
1785 if connected:
1786 pydevd_tracing.RestoreSysSetTraceFunc()
1787 sys.settrace(None)
1788 try:
1789 #not available in jython!
1790 threading.settrace(None) # for all future threads
1791 except:
1792 pass
Tor Norbye1aa2e092014-08-20 17:01:23 -07001793
1794 from pydev_monkey import undo_patch_thread_modules
1795 undo_patch_thread_modules()
1796
Tor Norbye3a2425a2013-11-04 10:16:08 -08001797 debugger = GetGlobalDebugger()
Tor Norbye1aa2e092014-08-20 17:01:23 -07001798
Tor Norbye3a2425a2013-11-04 10:16:08 -08001799 if debugger:
1800 debugger.trace_dispatch = None
Tor Norbye1aa2e092014-08-20 17:01:23 -07001801
Tor Norbye3a2425a2013-11-04 10:16:08 -08001802 debugger.SetTraceForFrameAndParents(GetFrame(), False)
Tor Norbye1aa2e092014-08-20 17:01:23 -07001803
Tor Norbye3a2425a2013-11-04 10:16:08 -08001804 debugger.exiting()
Tor Norbye1aa2e092014-08-20 17:01:23 -07001805
1806 killAllPydevThreads()
1807
Tor Norbye3a2425a2013-11-04 10:16:08 -08001808 connected = False
1809
1810class Dispatcher(object):
1811 def __init__(self):
1812 self.port = None
1813
1814 def connect(self, host, port):
1815 self.host = host
1816 self.port = port
1817 self.client = StartClient(self.host, self.port)
1818 self.reader = DispatchReader(self)
1819 self.reader.dontTraceMe = False #we run reader in the same thread so we don't want to loose tracing
1820 self.reader.run()
1821
1822 def close(self):
1823 try:
1824 self.reader.doKillPydevThread()
1825 except :
1826 pass
1827
1828class DispatchReader(ReaderThread):
1829 def __init__(self, dispatcher):
1830 self.dispatcher = dispatcher
1831 ReaderThread.__init__(self, self.dispatcher.client)
1832
1833 def handleExcept(self):
1834 ReaderThread.handleExcept(self)
1835
1836 def processCommand(self, cmd_id, seq, text):
1837 if cmd_id == 99:
1838 self.dispatcher.port = int(text)
1839 self.killReceived = True
1840
1841
Tor Norbye1aa2e092014-08-20 17:01:23 -07001842DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev
1843DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm
1844DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION
1845
Tor Norbye3a2425a2013-11-04 10:16:08 -08001846def dispatch():
Tor Norbye1aa2e092014-08-20 17:01:23 -07001847 setup = SetupHolder.setup
Tor Norbye3a2425a2013-11-04 10:16:08 -08001848 host = setup['client']
1849 port = setup['port']
Tor Norbye1aa2e092014-08-20 17:01:23 -07001850 if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION:
1851 dispatcher = Dispatcher()
1852 try:
1853 dispatcher.connect(host, port)
1854 port = dispatcher.port
1855 finally:
1856 dispatcher.close()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001857 return host, port
1858
1859
1860def settrace_forked():
Tor Norbye1aa2e092014-08-20 17:01:23 -07001861 '''
1862 When creating a fork from a process in the debugger, we need to reset the whole debugger environment!
1863 '''
Tor Norbye3a2425a2013-11-04 10:16:08 -08001864 host, port = dispatch()
1865
1866 import pydevd_tracing
1867 pydevd_tracing.RestoreSysSetTraceFunc()
1868
1869 if port is not None:
1870 global connected
1871 connected = False
Tor Norbyec667c1f2014-05-28 17:06:51 -07001872
1873 CustomFramesContainerInit()
1874
1875 settrace(
1876 host,
1877 port=port,
1878 suspend=False,
1879 trace_only_current_thread=False,
1880 overwrite_prev_trace=True,
1881 patch_multiprocessing=True,
1882 )
Tor Norbye1aa2e092014-08-20 17:01:23 -07001883
1884#=======================================================================================================================
1885# SetupHolder
1886#=======================================================================================================================
1887class SetupHolder:
1888
1889 setup = None
1890
1891
Tor Norbye3a2425a2013-11-04 10:16:08 -08001892#=======================================================================================================================
1893# main
1894#=======================================================================================================================
1895if __name__ == '__main__':
1896 # parse the command line. --file is our last argument that is required
1897 try:
1898 sys.original_argv = sys.argv[:]
1899 setup = processCommandLine(sys.argv)
Tor Norbye1aa2e092014-08-20 17:01:23 -07001900 SetupHolder.setup = setup
Tor Norbye3a2425a2013-11-04 10:16:08 -08001901 except ValueError:
1902 traceback.print_exc()
1903 usage(1)
1904
1905
Tor Norbye3a2425a2013-11-04 10:16:08 -08001906 fix_getpass.fixGetpass()
1907
Tor Norbye3a2425a2013-11-04 10:16:08 -08001908 pydev_log.debug("Executing file %s" % setup['file'])
1909 pydev_log.debug("arguments: %s"% str(sys.argv))
1910
1911
1912 pydevd_vm_type.SetupType(setup.get('vm_type', None))
1913
1914 if os.getenv('PYCHARM_DEBUG'):
1915 set_debug(setup)
1916
1917 DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
1918 DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('DEBUG_TRACE_BREAKPOINTS', -1)
1919 DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)
1920
1921 port = setup['port']
1922 host = setup['client']
Tor Norbyec667c1f2014-05-28 17:06:51 -07001923 f = setup['file']
1924 fix_app_engine_debug = False
Tor Norbye3a2425a2013-11-04 10:16:08 -08001925
Tor Norbye3a2425a2013-11-04 10:16:08 -08001926
Tor Norbye1aa2e092014-08-20 17:01:23 -07001927 try:
1928 import pydev_monkey
1929 except:
1930 pass #Not usable on jython 2.1
Tor Norbye3a2425a2013-11-04 10:16:08 -08001931 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001932 if setup['multiprocess']: # PyDev
1933 pydev_monkey.patch_new_process_functions()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001934
Tor Norbye1aa2e092014-08-20 17:01:23 -07001935 elif setup['multiproc']: # PyCharm
1936 pydev_log.debug("Started in multiproc mode\n")
1937 # Note: we're not inside method, so, no need for 'global'
1938 DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION
Tor Norbye3a2425a2013-11-04 10:16:08 -08001939
Tor Norbye1aa2e092014-08-20 17:01:23 -07001940 dispatcher = Dispatcher()
1941 try:
1942 dispatcher.connect(host, port)
1943 if dispatcher.port is not None:
1944 port = dispatcher.port
1945 pydev_log.debug("Received port %d\n" %port)
1946 pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
1947
Tor Norbyec667c1f2014-05-28 17:06:51 -07001948 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001949 pydev_monkey.patch_new_process_functions()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001950 except:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001951 pydev_log.error("Error patching process functions\n")
Tor Norbyec667c1f2014-05-28 17:06:51 -07001952 traceback.print_exc()
Tor Norbye1aa2e092014-08-20 17:01:23 -07001953 else:
1954 pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
1955 finally:
1956 dispatcher.close()
1957 else:
1958 pydev_log.info("pydev debugger: starting\n")
1959
1960 try:
1961 pydev_monkey.patch_new_process_functions_with_warning()
1962 except:
1963 pydev_log.error("Error patching process functions\n")
1964 traceback.print_exc()
1965
1966 # Only do this patching if we're not running with multiprocess turned on.
1967 if f.find('dev_appserver.py') != -1:
1968 if os.path.basename(f).startswith('dev_appserver.py'):
1969 appserver_dir = os.path.dirname(f)
1970 version_file = os.path.join(appserver_dir, 'VERSION')
1971 if os.path.exists(version_file):
1972 try:
1973 stream = open(version_file, 'r')
1974 try:
1975 for line in stream.read().splitlines():
1976 line = line.strip()
1977 if line.startswith('release:'):
1978 line = line[8:].strip()
1979 version = line.replace('"', '')
1980 version = version.split('.')
1981 if int(version[0]) > 1:
1982 fix_app_engine_debug = True
1983
1984 elif int(version[0]) == 1:
1985 if int(version[1]) >= 7:
1986 # Only fix from 1.7 onwards
1987 fix_app_engine_debug = True
1988 break
1989 finally:
1990 stream.close()
1991 except:
1992 traceback.print_exc()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001993
1994 try:
1995 # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible
1996 # on a run where we have a remote debug, we may have to be more careful because patching stackless means
1997 # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need
1998 # to call it again (because stackless provides no way of getting the last function which was registered
1999 # in set_schedule_callback).
2000 #
2001 # So, ideally, if there's an application using stackless and the application wants to use the remote debugger
2002 # and benefit from stackless debugging, the application itself must call:
2003 #
2004 # import pydevd_stackless
2005 # pydevd_stackless.patch_stackless()
2006 #
2007 # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached.
2008 import pydevd_stackless
2009 pydevd_stackless.patch_stackless()
2010 except:
2011 pass # It's ok not having stackless there...
2012
2013 if fix_app_engine_debug:
2014 sys.stderr.write("pydev debugger: google app engine integration enabled\n")
2015 curr_dir = os.path.dirname(__file__)
2016 app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py')
2017
2018 sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file)
2019 import json
2020 setup['pydevd'] = __file__
2021 sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),)
2022 sys.argv.insert(3, '--automatic_restart=no')
2023 sys.argv.insert(4, '--max_module_instances=1')
2024
2025 debugger = PyDB()
2026 # Run the dev_appserver
2027 debugger.run(setup['file'], None, None, set_trace=False)
2028
2029 else:
2030 # as to get here all our imports are already resolved, the psyco module can be
2031 # changed and we'll still get the speedups in the debugger, as those functions
2032 # are already compiled at this time.
2033 try:
2034 import psyco
2035 except ImportError:
2036 if hasattr(sys, 'exc_clear'): # jython does not have it
2037 sys.exc_clear() # don't keep the traceback -- clients don't want to see it
2038 pass # that's ok, no need to mock psyco if it's not available anyways
2039 else:
2040 # if it's available, let's change it for a stub (pydev already made use of it)
2041 import pydevd_psyco_stub
2042 sys.modules['psyco'] = pydevd_psyco_stub
Tor Norbye3a2425a2013-11-04 10:16:08 -08002043
Tor Norbye1aa2e092014-08-20 17:01:23 -07002044 debugger = PyDB()
Tor Norbye3a2425a2013-11-04 10:16:08 -08002045
Tor Norbye1aa2e092014-08-20 17:01:23 -07002046 if setup['save-signatures']:
2047 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
2048 sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
2049 else:
2050 debugger.signature_factory = SignatureFactory()
Tor Norbye3a2425a2013-11-04 10:16:08 -08002051
Tor Norbye1aa2e092014-08-20 17:01:23 -07002052 try:
2053 debugger.connect(host, port)
2054 except:
2055 sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
2056 traceback.print_exc()
2057 sys.exit(1)
Tor Norbye3a2425a2013-11-04 10:16:08 -08002058
Tor Norbye1aa2e092014-08-20 17:01:23 -07002059 connected = True # Mark that we're connected when started from inside ide.
Tor Norbye3a2425a2013-11-04 10:16:08 -08002060
Tor Norbye1aa2e092014-08-20 17:01:23 -07002061 debugger.run(setup['file'], None, None)