src/eric7/DebugClients/Python/DebugBase.py

branch
eric7
changeset 11048
aa0123c997cd
parent 10981
e80ffe75107c
child 11090
f5f5f5803935
equal deleted inserted replaced
11047:783fc3de315e 11048:aa0123c997cd
103 103
104 # frames, where we want to stop or release debugger 104 # frames, where we want to stop or release debugger
105 self.stopframe = None 105 self.stopframe = None
106 self.returnframe = None 106 self.returnframe = None
107 self.stop_everywhere = False 107 self.stop_everywhere = False
108
109 # frame, where opcode tracing could start
110 self.enterframe = None
111 self.traceOpcodes = False
108 112
109 self.__recursionDepth = -1 113 self.__recursionDepth = -1
110 self.setRecursionDepth(inspect.currentframe()) 114 self.setRecursionDepth(inspect.currentframe())
111 115
112 # background task to periodicaly check for client interactions 116 # background task to periodicaly check for client interactions
325 raise SystemExit 329 raise SystemExit
326 330
327 # check if we are still managing all exceptions 331 # check if we are still managing all exceptions
328 self._dbgClient.checkExceptionHook() 332 self._dbgClient.checkExceptionHook()
329 333
330 if event == "line": 334 if event in ("line", "opcode"): # handle both events identically
331 if self.stop_here(frame) or self.break_here(frame): 335 if self.stop_here(frame) or self.break_here(frame):
332 if ( 336 if (
333 self.stop_everywhere 337 self.stop_everywhere
334 and frame.f_back 338 and frame.f_back
335 and frame.f_back.f_code.co_name == "prepareJsonCommand" 339 and frame.f_back.f_code.co_name == "prepareJsonCommand"
391 and arg[0] in (StopIteration, GeneratorExit) 395 and arg[0] in (StopIteration, GeneratorExit)
392 ): 396 ):
393 self.user_exception(arg) 397 self.user_exception(arg)
394 return None 398 return None
395 399
396 if event == "c_call": 400 if event in ("c_call", "c_exception", "c_return"):
397 return None 401 # ignore C events
398 if event == "c_exception":
399 return None
400 if event == "c_return":
401 return None 402 return None
402 403
403 print( # __IGNORE_WARNING_M801__ 404 print( # __IGNORE_WARNING_M801__
404 "DebugBase.trace_dispatch: unknown debugging event: ", 405 "DebugBase.trace_dispatch: unknown debugging event: ",
405 repr(event), 406 repr(event),
421 if frame is None: 422 if frame is None:
422 frame = sys._getframe().f_back # Skip set_trace method 423 frame = sys._getframe().f_back # Skip set_trace method
423 424
424 stopOnHandleCommand = self._dbgClient.handleJsonCommand.__code__ 425 stopOnHandleCommand = self._dbgClient.handleJsonCommand.__code__
425 426
426 frame.f_trace = self.trace_dispatch 427 self.enterframe = frame
427 while frame.f_back is not None: 428 while frame is not None:
428 # stop at eric's debugger frame or a threading bootstrap 429 frame.f_trace = self.trace_dispatch
429 if frame.f_back.f_code == stopOnHandleCommand: 430 # We need f_trace_lines == True for the debugger to work. This should
430 frame.f_trace = self.trace_dispatch 431 # already be the case per default, but play it safe.
432 frame.f_trace_lines = True
433 frame = frame.f_back
434 if frame and frame.f_code is stopOnHandleCommand:
435 # stop at eric's debugger frame or a threading bootstrap
431 break 436 break
432 437
433 frame = frame.f_back
434
435 self.stop_everywhere = True 438 self.stop_everywhere = True
439 self.set_stepinstr()
436 sys.settrace(self.trace_dispatch) 440 sys.settrace(self.trace_dispatch)
437 sys.setprofile(self._dbgClient.callTraceEnabled) 441 sys.setprofile(self._dbgClient.callTraceEnabled)
438 442
439 def bootstrap(self, target, args, kwargs): 443 def bootstrap(self, target, args, kwargs):
440 """ 444 """
520 finally: 524 finally:
521 self.quitting = True 525 self.quitting = True
522 sys.settrace(None) 526 sys.settrace(None)
523 return exitcode 527 return exitcode
524 528
525 def _set_stopinfo(self, stopframe, returnframe, stoplineno=0): 529 def _set_trace_opcodes(self, traceOpcodes):
530 """
531 Protected method to set tracing on opcode level enabled or disabled.
532
533 @param traceOpcodes opcode tracing state
534 @type bool
535 """
536 if traceOpcodes != self.traceOpcodes:
537 stopOnHandleCommand = self._dbgClient.handleJsonCommand.__code__
538
539 self.traceOpcodes = traceOpcodes
540 frame = self.enterframe
541 while frame is not None:
542 frame.f_trace_opcodes = traceOpcodes
543 frame = frame.f_back
544 if frame and frame.f_code is stopOnHandleCommand:
545 # stop at eric's debugger frame or a threading bootstrap
546 break
547
548 def _set_stopinfo(self, stopframe, returnframe, stoplineno=0, traceOpcodes=False):
526 """ 549 """
527 Protected method to update the frame pointers. 550 Protected method to update the frame pointers.
528 551
529 @param stopframe the frame object where to stop 552 @param stopframe the frame object where to stop
530 @type frame object 553 @type frame object
531 @param returnframe the frame object where to stop on a function return 554 @param returnframe the frame object where to stop on a function return
532 @type frame object 555 @type frame object
533 @param stoplineno line number to stop at. If stoplineno is greater than 556 @param stoplineno line number to stop at. If stoplineno is greater than
534 or equal to 0, then stop at line greater than or equal to the 557 or equal to 0, then stop at line greater than or equal to the
535 stopline. If stoplineno is -1, then don't stop at all. 558 stopline. If stoplineno is -1, then don't stop at all. (defaults to 0)
536 @type int 559 @type int (optional)
560 @param traceOpcodes opcode tracing state (defaults to False)
561 @type bool (optional)
537 """ 562 """
538 self.stopframe = stopframe 563 self.stopframe = stopframe
539 self.returnframe = returnframe 564 self.returnframe = returnframe
540 # stoplineno >= 0 means: stop at line >= the stoplineno 565 # stoplineno >= 0 means: stop at line >= the stoplineno
541 # stoplineno -1 means: don't stop at all 566 # stoplineno -1 means: don't stop at all
543 568
544 if returnframe is not None: 569 if returnframe is not None:
545 # Ensure to be able to stop on the return frame 570 # Ensure to be able to stop on the return frame
546 returnframe.f_trace = self.trace_dispatch 571 returnframe.f_trace = self.trace_dispatch
547 self.stop_everywhere = False 572 self.stop_everywhere = False
573
574 self._set_trace_opcodes(traceOpcodes)
548 575
549 def set_continue(self, special): 576 def set_continue(self, special):
550 """ 577 """
551 Public method to stop only on next breakpoint. 578 Public method to stop only on next breakpoint.
552 579
583 """ 610 """
584 Public method to stop after one line of code. 611 Public method to stop after one line of code.
585 """ 612 """
586 self._set_stopinfo(None, None) 613 self._set_stopinfo(None, None)
587 self.stop_everywhere = True 614 self.stop_everywhere = True
615
616 def set_stepinstr(self):
617 """
618 Public method to stop before the next instruction.
619 """
620 self._set_stopinfo(None, None, opcode=True)
588 621
589 def set_next(self, frame): 622 def set_next(self, frame):
590 """ 623 """
591 Public method to stop on the next line in or below the given frame. 624 Public method to stop on the next line in or below the given frame.
592 625

eric ide

mercurial