DebugClients/Python3/DebugBase.py

branch
debugger speed
changeset 5012
be693f11da53
parent 5007
e2fa12bb0f53
child 5041
f00a4c8bcbbd
equal deleted inserted replaced
5007:e2fa12bb0f53 5012:be693f11da53
71 self._mainThread = True 71 self._mainThread = True
72 72
73 self.breaks = self._dbgClient.breakpoints 73 self.breaks = self._dbgClient.breakpoints
74 self.tracePythonLibs(0) 74 self.tracePythonLibs(0)
75 75
76 self.__event = "" 76 self.__isBroken = False
77 self.__isBroken = ""
78 self.cFrame = None 77 self.cFrame = None
79 78
80 # current frame we are at 79 # current frame we are at
81 self.currentFrame = None 80 self.currentFrame = None
82 81
231 230
232 This specialty is to check the connection to the debug server 231 This specialty is to check the connection to the debug server
233 for new events (i.e. new breakpoints) while we are going through 232 for new events (i.e. new breakpoints) while we are going through
234 the code. 233 the code.
235 234
236 @param frame The current stack frame. 235 @param frame The current stack frame
237 @param event The trace event (string) 236 @type frame object
237 @param event The trace event
238 @type str
238 @param arg The arguments 239 @param arg The arguments
240 @type depends on the previous event parameter
239 @return local trace function 241 @return local trace function
242 @rtype trace function or None
243 @exception bdb.BdbQuit
240 """ 244 """
241 if self.quitting: 245 if self.quitting:
242 return # None 246 return # None
243 247
244 # give the client a chance to push through new break points. 248 # give the client a chance to push through new break points.
245 self._dbgClient.eventPoll() 249 self._dbgClient.eventPoll()
246 250
247 self.__event == event
248 self.__isBroken = False
249
250 if event == 'line': 251 if event == 'line':
251 return self.dispatch_line(frame) 252 if self.stop_here(frame) or self.break_here(frame):
253 self.user_line(frame)
254 if self.quitting:
255 raise bdb.BdbQuit
256 return
257
252 if event == 'call': 258 if event == 'call':
253 return self.dispatch_call(frame, arg) 259 if self.botframe is None:
254 if event == 'return': 260 # First call of dispatch since reset()
255 return self.dispatch_return(frame, arg) 261 # (CT) Note that this may also be None!
256 if event == 'exception': 262 self.botframe = frame.f_back
257 return self.dispatch_exception(frame, arg) 263 return self.trace_dispatch
258 if event == 'c_call': 264
259 return self.trace_dispatch 265 if not (self.stop_here(frame) or self.break_anywhere(frame)):
260 if event == 'c_exception': 266 # No need to trace this function
261 return self.trace_dispatch 267 return
262 if event == 'c_return':
263 return self.trace_dispatch
264 print('bdb.Bdb.dispatch: unknown debugging event: ', repr(event)) # __IGNORE_WARNING__
265 return self.trace_dispatch
266
267 def dispatch_line(self, frame):
268 """
269 Public method reimplemented from bdb.py to do some special things.
270
271 This speciality is to check the connection to the debug server
272 for new events (i.e. new breakpoints) while we are going through
273 the code.
274
275 @param frame The current stack frame.
276 @return local trace function
277 @exception bdb.BdbQuit raised to indicate the end of the debug session
278 """
279 if self.stop_here(frame) or self.break_here(frame):
280 self.user_line(frame)
281 if self.quitting: 268 if self.quitting:
282 raise bdb.BdbQuit 269 raise bdb.BdbQuit
283 return self.trace_dispatch 270 return self.trace_dispatch
284 271
285 def dispatch_return(self, frame, arg): 272 if event == 'return':
286 """ 273 if self.stop_here(frame) or frame == self.returnframe:
287 Public method reimplemented from bdb.py to handle passive mode cleanly. 274 # Ignore return events in generator except when stepping.
288 275 if self.stopframe and frame.f_code.co_flags & CO_GENERATOR:
289 @param frame The current stack frame. 276 return
290 @param arg The arguments 277 # The program has finished if we have just left the first frame
291 @return local trace function 278 if frame == self._dbgClient.mainFrame and \
292 @exception bdb.BdbQuit raised to indicate the end of the debug session 279 self._mainThread:
293 """ 280 atexit._run_exitfuncs()
294 if self.stop_here(frame) or frame == self.returnframe: 281 self._dbgClient.progTerminated(arg)
295 # Ignore return events in generator except when stepping. 282 elif frame is not self.stepFrame:
296 if self.stopframe and frame.f_code.co_flags & CO_GENERATOR: 283 self.stepFrame = None
297 return self.trace_dispatch 284 self.user_line(frame)
298 self.user_return(frame, arg) 285
299 if self.quitting and not self._dbgClient.passive: 286 if self.quitting and not self._dbgClient.passive:
300 raise bdb.BdbQuit 287 raise bdb.BdbQuit
301 return self.trace_dispatch 288 return
302 289
303 def dispatch_exception(self, frame, arg): 290 if event == 'exception':
304 """ 291 if not self.__skipFrame(frame):
305 Public method reimplemented from bdb.py to always call user_exception. 292 # When stepping with next/until/return in a generator frame,
306 293 # skip the internal StopIteration exception (with no traceback)
307 @param frame The current stack frame. 294 # triggered by a subiterator run with the 'yield from'
308 @param arg The arguments 295 # statement.
309 @return local trace function 296 if not (frame.f_code.co_flags & CO_GENERATOR and
310 @exception bdb.BdbQuit raised to indicate the end of the debug session 297 arg[0] is StopIteration and arg[2] is None):
311 """ 298 self.user_exception(frame, arg)
312 if not self.__skipFrame(frame): 299 if self.quitting:
313 # When stepping with next/until/return in a generator frame, 300 raise bdb.BdbQuit
314 # skip the internal StopIteration exception (with no traceback) 301 # Stop at the StopIteration or GeneratorExit exception when the user
315 # triggered by a subiterator run with the 'yield from' 302 # has set stopframe in a generator by issuing a return command, or a
316 # statement. 303 # next/until command at the last statement in the generator before the
317 if not (frame.f_code.co_flags & CO_GENERATOR and 304 # exception.
318 arg[0] is StopIteration and arg[2] is None): 305 elif (self.stopframe and frame is not self.stopframe and
306 self.stopframe.f_code.co_flags & CO_GENERATOR and
307 arg[0] in (StopIteration, GeneratorExit)):
319 self.user_exception(frame, arg) 308 self.user_exception(frame, arg)
320 if self.quitting: 309 if self.quitting:
321 raise bdb.BdbQuit 310 raise bdb.BdbQuit
322 # Stop at the StopIteration or GeneratorExit exception when the user 311 return
323 # has set stopframe in a generator by issuing a return command, or a 312
324 # next/until command at the last statement in the generator before the 313 if event == 'c_call':
325 # exception. 314 return
326 elif (self.stopframe and frame is not self.stopframe and 315 if event == 'c_exception':
327 self.stopframe.f_code.co_flags & CO_GENERATOR and 316 return
328 arg[0] in (StopIteration, GeneratorExit)): 317 if event == 'c_return':
329 self.user_exception(frame, arg) 318 return
330 if self.quitting: 319 print('bdb.Bdb.dispatch: unknown debugging event: ', repr(event)) # __IGNORE_WARNING__
331 raise bdb.BdbQuit
332
333 return self.trace_dispatch 320 return self.trace_dispatch
334 321
335 def set_trace(self, frame=None): 322 def set_trace(self, frame=None):
336 """ 323 """
337 Public method reimplemented from bdb.py to do some special setup. 324 Public method reimplemented from bdb.py to do some special setup.
745 732
746 self.__isBroken = True 733 self.__isBroken = True
747 734
748 self._dbgClient.write('{0}{1}\n'.format(ResponseLine, str(stack))) 735 self._dbgClient.write('{0}{1}\n'.format(ResponseLine, str(stack)))
749 self._dbgClient.eventLoop() 736 self._dbgClient.eventLoop()
737
738 self.__isBroken = False
750 739
751 def user_exception(self, frame, excinfo, unhandled=False): 740 def user_exception(self, frame, excinfo, unhandled=False):
752 """ 741 """
753 Public method reimplemented to report an exception to the debug server. 742 Public method reimplemented to report an exception to the debug server.
754 743
874 stack.append(tb.tb_frame) 863 stack.append(tb.tb_frame)
875 tb = tb.tb_next 864 tb = tb.tb_next
876 tb = None 865 tb = None
877 return stack 866 return stack
878 867
879 def user_return(self, frame, retval):
880 """
881 Public method reimplemented to report program termination to the debug
882 server.
883
884 @param frame the frame object
885 @param retval the return value of the program
886 """
887 # The program has finished if we have just left the first frame.
888 if frame == self._dbgClient.mainFrame and \
889 self._mainThread:
890 atexit._run_exitfuncs()
891 self._dbgClient.progTerminated(retval)
892 elif frame is not self.stepFrame:
893 self.stepFrame = None
894 self.user_line(frame)
895
896 def stop_here(self, frame): 868 def stop_here(self, frame):
897 """ 869 """
898 Public method reimplemented to filter out debugger files. 870 Public method reimplemented to filter out debugger files.
899 871
900 Tracing is turned off for files that are part of the 872 Tracing is turned off for files that are part of the
952 924
953 def isBroken(self): 925 def isBroken(self):
954 """ 926 """
955 Public method to return the broken state of the debugger. 927 Public method to return the broken state of the debugger.
956 928
957 @return flag indicating the broken state (boolean) 929 @return flag indicating the broken state
930 @rtype bool
958 """ 931 """
959 return self.__isBroken 932 return self.__isBroken
960
961 def getEvent(self):
962 """
963 Protected method to return the last debugger event.
964
965 @return last debugger event (string)
966 """
967 return self.__event
968 933
969 # 934 #
970 # eflag: noqa = M702 935 # eflag: noqa = M702

eric ide

mercurial