diff -r be693f11da53 -r f00a4c8bcbbd DebugClients/Python3/DebugBase.py --- a/DebugClients/Python3/DebugBase.py Sat Jul 02 21:58:09 2016 +0200 +++ b/DebugClients/Python3/DebugBase.py Sun Jul 17 22:40:53 2016 +0200 @@ -18,6 +18,7 @@ from DebugProtocol import ResponseClearWatch, ResponseClearBreak, \ ResponseLine, ResponseSyntax, ResponseException, CallTrace from DebugUtilities import getargvalues, formatargvalues +from BreakpointWatch import Breakpoint, Watch gRecursionLimit = 64 @@ -70,7 +71,6 @@ self._dbgClient = dbgClient self._mainThread = True - self.breaks = self._dbgClient.breakpoints self.tracePythonLibs(0) self.__isBroken = False @@ -262,7 +262,9 @@ self.botframe = frame.f_back return self.trace_dispatch - if not (self.stop_here(frame) or self.break_anywhere(frame)): + if not (self.stop_here(frame) or + self.break_anywhere(frame) or + Watch.watches != []): # No need to trace this function return if self.quitting: @@ -391,121 +393,6 @@ self._fnCache[fn] = fixedName return fixedName - def set_watch(self, cond, temporary=False): - """ - Public method to set a watch expression. - - @param cond expression of the watch expression (string) - @param temporary flag indicating a temporary watch expression (boolean) - """ - bp = bdb.Breakpoint("Watch", 0, temporary, cond) - if cond.endswith('??created??') or cond.endswith('??changed??'): - bp.condition, bp.special = cond.split() - else: - bp.condition = cond - bp.special = "" - bp.values = {} - if "Watch" not in self.breaks: - self.breaks["Watch"] = 1 - else: - self.breaks["Watch"] += 1 - - def clear_watch(self, cond): - """ - Public method to clear a watch expression. - - @param cond expression of the watch expression to be cleared (string) - """ - try: - possibles = bdb.Breakpoint.bplist["Watch", 0] - for i in range(0, len(possibles)): - b = possibles[i] - if b.cond == cond: - b.deleteMe() - self.breaks["Watch"] -= 1 - if self.breaks["Watch"] == 0: - del self.breaks["Watch"] - break - except KeyError: - pass - - def get_watch(self, cond): - """ - Public method to get a watch expression. - - @param cond expression of the watch expression to be cleared (string) - @return reference to the watch point - """ - possibles = bdb.Breakpoint.bplist["Watch", 0] - for i in range(0, len(possibles)): - b = possibles[i] - if b.cond == cond: - return b - - def __do_clearWatch(self, cond): - """ - Private method called to clear a temporary watch expression. - - @param cond expression of the watch expression to be cleared (string) - """ - self.clear_watch(cond) - self._dbgClient.write('{0}{1}\n'.format(ResponseClearWatch, cond)) - - def __effective(self, frame): - """ - Private method to determine, if a watch expression is effective. - - @param frame the current execution frame - @return tuple of watch expression and a flag to indicate, that a - temporary watch expression may be deleted (bdb.Breakpoint, boolean) - """ - possibles = bdb.Breakpoint.bplist["Watch", 0] - for i in range(0, len(possibles)): - b = possibles[i] - if not b.enabled: - continue - if not b.cond: - # watch expression without expression shouldn't occur, - # just ignore it - continue - try: - val = eval(b.condition, frame.f_globals, frame.f_locals) - if b.special: - if b.special == '??created??': - if b.values[frame][0] == 0: - b.values[frame][0] = 1 - b.values[frame][1] = val - return (b, True) - else: - continue - b.values[frame][0] = 1 - if b.special == '??changed??': - if b.values[frame][1] != val: - b.values[frame][1] = val - if b.values[frame][2] > 0: - b.values[frame][2] -= 1 - continue - else: - return (b, True) - else: - continue - continue - if val: - if b.ignore > 0: - b.ignore -= 1 - continue - else: - return (b, True) - except Exception: - if b.special: - try: - b.values[frame][0] = 0 - except KeyError: - b.values[frame] = [0, None, b.ignore] - continue - - return (None, False) - def break_here(self, frame): """ Public method reimplemented from bdb.py to fix the filename from the @@ -514,34 +401,25 @@ See fix_frame_filename for more info. @param frame the frame object - @return flag indicating the break status (boolean) + @type frame object + @return flag indicating the break status + @rtype bool """ filename = self.fix_frame_filename(frame) - if filename not in self.breaks and "Watch" not in self.breaks: - return False - - if filename in self.breaks: - lineno = frame.f_lineno - if lineno not in self.breaks[filename]: - # The line itself has no breakpoint, but maybe the line is the - # first line of a function with breakpoint set by function - # name. - lineno = frame.f_code.co_firstlineno - if lineno in self.breaks[filename]: + if (filename, frame.f_lineno) in Breakpoint.breaks: + bp, flag = Breakpoint.effectiveBreak( + filename, frame.f_lineno, frame) + if bp: # flag says ok to delete temp. bp - (bp, flag) = bdb.effective(filename, lineno, frame) - if bp: - self.currentbp = bp.number - if (flag and bp.temporary): - self.__do_clear(filename, lineno) - return True + if flag and bp.temporary: + self.__do_clearBreak(filename, frame.f_lineno) + return True - if "Watch" in self.breaks: - # flag says ok to delete temp. bp - (bp, flag) = self.__effective(frame) + if Watch.watches != []: + bp, flag = Watch.effectiveWatch(frame) if bp: - self.currentbp = bp.number - if (flag and bp.temporary): + # flag says ok to delete temp. watch + if flag and bp.temporary: self.__do_clearWatch(bp.cond) return True @@ -555,80 +433,34 @@ (see fix_frame_filename for more info). @param frame the frame object - @return flag indicating the break status (boolean) - """ - return \ - self.fix_frame_filename(frame) in self.breaks or \ - ("Watch" in self.breaks and self.breaks["Watch"]) - - def set_break(self, filename, lineno, temporary=0, cond=None, - funcname=None): - """ - Public method reimplemented from bdb.py to normalize the filename and - set as a breakpoint. - - @param filename the filename where a breakpoint is set - @type str - @param lineno the line number of the breakpoint - @type int - @keyparam temporary flag to indicate a temporary breakpoint - @type int - @keyparam cond Python expression which dynamically enables this bp - @type str - @keyparam funcname name of the function (unused) - @type str or None - """ - filename = os.path.abspath(filename) - list = self.breaks.setdefault(filename, []) - if lineno not in list: - list.append(lineno) - bdb.Breakpoint(filename, lineno, temporary, cond, funcname) - - def get_break(self, filename, lineno): + @param frame object + @return flag indicating the break status + @rtype bool """ - Public method reimplemented from bdb.py to get the first breakpoint of - a particular line. - - Because eric6 supports only one breakpoint per line, this overwritten - method will return this one and only breakpoint. - - @param filename the filename of the bp to retrieve - @type str - @param lineno the linenumber of the bp to retrieve - @type int - @return breakpoint or None, if there is no bp - @rtype breakpoint object or None - """ - return (lineno in self.breaks.get(filename, []) and - bdb.Breakpoint.bplist[filename, lineno][0] or None) - - def clear_break(self, filename, lineno): - """ - Public method reimplemented from bdb.py to clear a breakpoint. - - @param filename the filename of the bp to retrieve - @type str - @param lineno the linenumber of the bp to retrieve - @type int - """ - if (filename, lineno) not in bdb.Breakpoint.bplist: - return - # If there's only one bp in the list for that file,line - # pair, then remove the breaks entry - for bp in bdb.Breakpoint.bplist[filename, lineno][:]: - bp.deleteMe() - self._prune_breaks(filename, lineno) + return self.fix_frame_filename(frame) in Breakpoint.breakInFile - def __do_clear(self, filename, lineno): + def __do_clearBreak(self, filename, lineno): """ Private method called to clear a temporary breakpoint. @param filename name of the file the bp belongs to + @type str @param lineno linenumber of the bp + @type int """ - self.clear_break(filename, lineno) - self._dbgClient.write('{0}{1},{2:d}\n'.format( - ResponseClearBreak, filename, lineno)) + Breakpoint.clear_break(filename, lineno) + self._dbgClient.write('%s%s,%d\n' % (ResponseClearBreak, filename, + lineno)) + + def __do_clearWatch(self, cond): + """ + Private method called to clear a temporary watch expression. + + @param cond expression of the watch expression to be cleared + @type str + """ + Watch.clear_watch(cond) + self._dbgClient.write('%s%s\n' % (ResponseClearWatch, cond)) def getStack(self): """