DebugClients/Python3/DebugBase.py

branch
debugger speed
changeset 5041
f00a4c8bcbbd
parent 5012
be693f11da53
child 5044
630b9f290a77
equal deleted inserted replaced
5012:be693f11da53 5041:f00a4c8bcbbd
16 from inspect import CO_GENERATOR 16 from inspect import CO_GENERATOR
17 17
18 from DebugProtocol import ResponseClearWatch, ResponseClearBreak, \ 18 from DebugProtocol import ResponseClearWatch, ResponseClearBreak, \
19 ResponseLine, ResponseSyntax, ResponseException, CallTrace 19 ResponseLine, ResponseSyntax, ResponseException, CallTrace
20 from DebugUtilities import getargvalues, formatargvalues 20 from DebugUtilities import getargvalues, formatargvalues
21 from BreakpointWatch import Breakpoint, Watch
21 22
22 gRecursionLimit = 64 23 gRecursionLimit = 64
23 24
24 25
25 def printerr(s): 26 def printerr(s):
68 bdb.Bdb.__init__(self) 69 bdb.Bdb.__init__(self)
69 70
70 self._dbgClient = dbgClient 71 self._dbgClient = dbgClient
71 self._mainThread = True 72 self._mainThread = True
72 73
73 self.breaks = self._dbgClient.breakpoints
74 self.tracePythonLibs(0) 74 self.tracePythonLibs(0)
75 75
76 self.__isBroken = False 76 self.__isBroken = False
77 self.cFrame = None 77 self.cFrame = None
78 78
260 # First call of dispatch since reset() 260 # First call of dispatch since reset()
261 # (CT) Note that this may also be None! 261 # (CT) Note that this may also be None!
262 self.botframe = frame.f_back 262 self.botframe = frame.f_back
263 return self.trace_dispatch 263 return self.trace_dispatch
264 264
265 if not (self.stop_here(frame) or self.break_anywhere(frame)): 265 if not (self.stop_here(frame) or
266 self.break_anywhere(frame) or
267 Watch.watches != []):
266 # No need to trace this function 268 # No need to trace this function
267 return 269 return
268 if self.quitting: 270 if self.quitting:
269 raise bdb.BdbQuit 271 raise bdb.BdbQuit
270 return self.trace_dispatch 272 return self.trace_dispatch
389 fixedName = frame.f_code.co_filename 391 fixedName = frame.f_code.co_filename
390 # update cache 392 # update cache
391 self._fnCache[fn] = fixedName 393 self._fnCache[fn] = fixedName
392 return fixedName 394 return fixedName
393 395
394 def set_watch(self, cond, temporary=False):
395 """
396 Public method to set a watch expression.
397
398 @param cond expression of the watch expression (string)
399 @param temporary flag indicating a temporary watch expression (boolean)
400 """
401 bp = bdb.Breakpoint("Watch", 0, temporary, cond)
402 if cond.endswith('??created??') or cond.endswith('??changed??'):
403 bp.condition, bp.special = cond.split()
404 else:
405 bp.condition = cond
406 bp.special = ""
407 bp.values = {}
408 if "Watch" not in self.breaks:
409 self.breaks["Watch"] = 1
410 else:
411 self.breaks["Watch"] += 1
412
413 def clear_watch(self, cond):
414 """
415 Public method to clear a watch expression.
416
417 @param cond expression of the watch expression to be cleared (string)
418 """
419 try:
420 possibles = bdb.Breakpoint.bplist["Watch", 0]
421 for i in range(0, len(possibles)):
422 b = possibles[i]
423 if b.cond == cond:
424 b.deleteMe()
425 self.breaks["Watch"] -= 1
426 if self.breaks["Watch"] == 0:
427 del self.breaks["Watch"]
428 break
429 except KeyError:
430 pass
431
432 def get_watch(self, cond):
433 """
434 Public method to get a watch expression.
435
436 @param cond expression of the watch expression to be cleared (string)
437 @return reference to the watch point
438 """
439 possibles = bdb.Breakpoint.bplist["Watch", 0]
440 for i in range(0, len(possibles)):
441 b = possibles[i]
442 if b.cond == cond:
443 return b
444
445 def __do_clearWatch(self, cond):
446 """
447 Private method called to clear a temporary watch expression.
448
449 @param cond expression of the watch expression to be cleared (string)
450 """
451 self.clear_watch(cond)
452 self._dbgClient.write('{0}{1}\n'.format(ResponseClearWatch, cond))
453
454 def __effective(self, frame):
455 """
456 Private method to determine, if a watch expression is effective.
457
458 @param frame the current execution frame
459 @return tuple of watch expression and a flag to indicate, that a
460 temporary watch expression may be deleted (bdb.Breakpoint, boolean)
461 """
462 possibles = bdb.Breakpoint.bplist["Watch", 0]
463 for i in range(0, len(possibles)):
464 b = possibles[i]
465 if not b.enabled:
466 continue
467 if not b.cond:
468 # watch expression without expression shouldn't occur,
469 # just ignore it
470 continue
471 try:
472 val = eval(b.condition, frame.f_globals, frame.f_locals)
473 if b.special:
474 if b.special == '??created??':
475 if b.values[frame][0] == 0:
476 b.values[frame][0] = 1
477 b.values[frame][1] = val
478 return (b, True)
479 else:
480 continue
481 b.values[frame][0] = 1
482 if b.special == '??changed??':
483 if b.values[frame][1] != val:
484 b.values[frame][1] = val
485 if b.values[frame][2] > 0:
486 b.values[frame][2] -= 1
487 continue
488 else:
489 return (b, True)
490 else:
491 continue
492 continue
493 if val:
494 if b.ignore > 0:
495 b.ignore -= 1
496 continue
497 else:
498 return (b, True)
499 except Exception:
500 if b.special:
501 try:
502 b.values[frame][0] = 0
503 except KeyError:
504 b.values[frame] = [0, None, b.ignore]
505 continue
506
507 return (None, False)
508
509 def break_here(self, frame): 396 def break_here(self, frame):
510 """ 397 """
511 Public method reimplemented from bdb.py to fix the filename from the 398 Public method reimplemented from bdb.py to fix the filename from the
512 frame. 399 frame.
513 400
514 See fix_frame_filename for more info. 401 See fix_frame_filename for more info.
515 402
516 @param frame the frame object 403 @param frame the frame object
517 @return flag indicating the break status (boolean) 404 @type frame object
405 @return flag indicating the break status
406 @rtype bool
518 """ 407 """
519 filename = self.fix_frame_filename(frame) 408 filename = self.fix_frame_filename(frame)
520 if filename not in self.breaks and "Watch" not in self.breaks: 409 if (filename, frame.f_lineno) in Breakpoint.breaks:
521 return False 410 bp, flag = Breakpoint.effectiveBreak(
522 411 filename, frame.f_lineno, frame)
523 if filename in self.breaks: 412 if bp:
524 lineno = frame.f_lineno
525 if lineno not in self.breaks[filename]:
526 # The line itself has no breakpoint, but maybe the line is the
527 # first line of a function with breakpoint set by function
528 # name.
529 lineno = frame.f_code.co_firstlineno
530 if lineno in self.breaks[filename]:
531 # flag says ok to delete temp. bp 413 # flag says ok to delete temp. bp
532 (bp, flag) = bdb.effective(filename, lineno, frame) 414 if flag and bp.temporary:
533 if bp: 415 self.__do_clearBreak(filename, frame.f_lineno)
534 self.currentbp = bp.number 416 return True
535 if (flag and bp.temporary): 417
536 self.__do_clear(filename, lineno) 418 if Watch.watches != []:
537 return True 419 bp, flag = Watch.effectiveWatch(frame)
538
539 if "Watch" in self.breaks:
540 # flag says ok to delete temp. bp
541 (bp, flag) = self.__effective(frame)
542 if bp: 420 if bp:
543 self.currentbp = bp.number 421 # flag says ok to delete temp. watch
544 if (flag and bp.temporary): 422 if flag and bp.temporary:
545 self.__do_clearWatch(bp.cond) 423 self.__do_clearWatch(bp.cond)
546 return True 424 return True
547 425
548 return False 426 return False
549 427
553 431
554 These speciality is to fix the filename from the frame 432 These speciality is to fix the filename from the frame
555 (see fix_frame_filename for more info). 433 (see fix_frame_filename for more info).
556 434
557 @param frame the frame object 435 @param frame the frame object
558 @return flag indicating the break status (boolean) 436 @param frame object
559 """ 437 @return flag indicating the break status
560 return \ 438 @rtype bool
561 self.fix_frame_filename(frame) in self.breaks or \ 439 """
562 ("Watch" in self.breaks and self.breaks["Watch"]) 440 return self.fix_frame_filename(frame) in Breakpoint.breakInFile
563 441
564 def set_break(self, filename, lineno, temporary=0, cond=None, 442 def __do_clearBreak(self, filename, lineno):
565 funcname=None): 443 """
566 """ 444 Private method called to clear a temporary breakpoint.
567 Public method reimplemented from bdb.py to normalize the filename and 445
568 set as a breakpoint. 446 @param filename name of the file the bp belongs to
569
570 @param filename the filename where a breakpoint is set
571 @type str 447 @type str
572 @param lineno the line number of the breakpoint 448 @param lineno linenumber of the bp
573 @type int 449 @type int
574 @keyparam temporary flag to indicate a temporary breakpoint 450 """
575 @type int 451 Breakpoint.clear_break(filename, lineno)
576 @keyparam cond Python expression which dynamically enables this bp 452 self._dbgClient.write('%s%s,%d\n' % (ResponseClearBreak, filename,
453 lineno))
454
455 def __do_clearWatch(self, cond):
456 """
457 Private method called to clear a temporary watch expression.
458
459 @param cond expression of the watch expression to be cleared
577 @type str 460 @type str
578 @keyparam funcname name of the function (unused) 461 """
579 @type str or None 462 Watch.clear_watch(cond)
580 """ 463 self._dbgClient.write('%s%s\n' % (ResponseClearWatch, cond))
581 filename = os.path.abspath(filename)
582 list = self.breaks.setdefault(filename, [])
583 if lineno not in list:
584 list.append(lineno)
585 bdb.Breakpoint(filename, lineno, temporary, cond, funcname)
586
587 def get_break(self, filename, lineno):
588 """
589 Public method reimplemented from bdb.py to get the first breakpoint of
590 a particular line.
591
592 Because eric6 supports only one breakpoint per line, this overwritten
593 method will return this one and only breakpoint.
594
595 @param filename the filename of the bp to retrieve
596 @type str
597 @param lineno the linenumber of the bp to retrieve
598 @type int
599 @return breakpoint or None, if there is no bp
600 @rtype breakpoint object or None
601 """
602 return (lineno in self.breaks.get(filename, []) and
603 bdb.Breakpoint.bplist[filename, lineno][0] or None)
604
605 def clear_break(self, filename, lineno):
606 """
607 Public method reimplemented from bdb.py to clear a breakpoint.
608
609 @param filename the filename of the bp to retrieve
610 @type str
611 @param lineno the linenumber of the bp to retrieve
612 @type int
613 """
614 if (filename, lineno) not in bdb.Breakpoint.bplist:
615 return
616 # If there's only one bp in the list for that file,line
617 # pair, then remove the breaks entry
618 for bp in bdb.Breakpoint.bplist[filename, lineno][:]:
619 bp.deleteMe()
620 self._prune_breaks(filename, lineno)
621
622 def __do_clear(self, filename, lineno):
623 """
624 Private method called to clear a temporary breakpoint.
625
626 @param filename name of the file the bp belongs to
627 @param lineno linenumber of the bp
628 """
629 self.clear_break(filename, lineno)
630 self._dbgClient.write('{0}{1},{2:d}\n'.format(
631 ResponseClearBreak, filename, lineno))
632 464
633 def getStack(self): 465 def getStack(self):
634 """ 466 """
635 Public method to get the stack. 467 Public method to get the stack.
636 468

eric ide

mercurial