DebugClients/Python/DebugBase.py

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

eric ide

mercurial