DebugClients/Python/DebugBase.py

changeset 5141
bc64243b7672
parent 5126
d28b92dabc2b
parent 5140
01484c0afbc6
child 5144
1ab536d25072
equal deleted inserted replaced
5126:d28b92dabc2b 5141:bc64243b7672
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the debug base class.
8 """
9
10 import sys
11 import bdb
12 import os
13 import types
14 import atexit
15 import inspect
16 import ctypes
17
18 from DebugProtocol import ResponseClearWatch, ResponseClearBreak, \
19 ResponseLine, ResponseSyntax, ResponseException, CallTrace
20
21 gRecursionLimit = 64
22
23
24 def printerr(s):
25 """
26 Module function used for debugging the debug client.
27
28 @param s data to be printed
29 """
30 sys.__stderr__.write('%s\n' % unicode(s))
31 sys.__stderr__.flush()
32
33
34 def setRecursionLimit(limit):
35 """
36 Module function to set the recursion limit.
37
38 @param limit recursion limit (integer)
39 """
40 global gRecursionLimit
41 gRecursionLimit = limit
42
43
44 class DebugBase(bdb.Bdb):
45 """
46 Class implementing base class of the debugger.
47
48 Provides simple wrapper methods around bdb for the 'owning' client to
49 call to step etc.
50 """
51 def __init__(self, dbgClient):
52 """
53 Constructor
54
55 @param dbgClient the owning client
56 """
57 bdb.Bdb.__init__(self)
58
59 self._dbgClient = dbgClient
60 self._mainThread = 1
61
62 self.breaks = self._dbgClient.breakpoints
63
64 self.__event = ""
65 self.__isBroken = ""
66 self.cFrame = None
67
68 # current frame we are at
69 self.currentFrame = None
70
71 # frame that we are stepping in, can be different than currentFrame
72 self.stepFrame = None
73
74 # provide a hook to perform a hard breakpoint
75 # Use it like this:
76 # if hasattr(sys, 'breakpoint): sys.breakpoint()
77 sys.breakpoint = self.set_trace
78
79 # initialize parent
80 bdb.Bdb.reset(self)
81
82 self.__recursionDepth = -1
83 self.setRecursionDepth(inspect.currentframe())
84
85 def getCurrentFrame(self):
86 """
87 Public method to return the current frame.
88
89 @return the current frame
90 """
91 return self.currentFrame
92
93 def getFrameLocals(self, frmnr=0):
94 """
95 Public method to return the locals dictionary of the current frame
96 or a frame below.
97
98 @keyparam frmnr distance of frame to get locals dictionary of. 0 is
99 the current frame (int)
100 @return locals dictionary of the frame
101 """
102 f = self.currentFrame
103 while f is not None and frmnr > 0:
104 f = f.f_back
105 frmnr -= 1
106 return f.f_locals
107
108 def storeFrameLocals(self, frmnr=0):
109 """
110 Public method to store the locals into the frame, so an access to
111 frame.f_locals returns the last data.
112
113 @keyparam frmnr distance of frame to store locals dictionary to. 0 is
114 the current frame (int)
115 """
116 cf = self.currentFrame
117 while cf is not None and frmnr > 0:
118 cf = cf.f_back
119 frmnr -= 1
120 ctypes.pythonapi.PyFrame_LocalsToFast(
121 ctypes.py_object(cf),
122 ctypes.c_int(0))
123
124 def step(self, traceMode):
125 """
126 Public method to perform a step operation in this thread.
127
128 @param traceMode If it is non-zero, then the step is a step into,
129 otherwise it is a step over.
130 """
131 self.stepFrame = self.currentFrame
132
133 if traceMode:
134 self.currentFrame = None
135 self.set_step()
136 else:
137 self.set_next(self.currentFrame)
138
139 def stepOut(self):
140 """
141 Public method to perform a step out of the current call.
142 """
143 self.stepFrame = self.currentFrame
144 self.set_return(self.currentFrame)
145
146 def go(self, special):
147 """
148 Public method to resume the thread.
149
150 It resumes the thread stopping only at breakpoints or exceptions.
151
152 @param special flag indicating a special continue operation
153 """
154 self.currentFrame = None
155 self.set_continue(special)
156
157 def setRecursionDepth(self, frame):
158 """
159 Public method to determine the current recursion depth.
160
161 @param frame The current stack frame.
162 """
163 self.__recursionDepth = 0
164 while frame is not None:
165 self.__recursionDepth += 1
166 frame = frame.f_back
167
168 def profile(self, frame, event, arg):
169 """
170 Public method used to trace some stuff independent of the debugger
171 trace function.
172
173 @param frame current stack frame.
174 @param event trace event (string)
175 @param arg arguments
176 @exception RuntimeError raised to indicate too many recursions
177 """
178 if event == 'return':
179 self.cFrame = frame.f_back
180 self.__recursionDepth -= 1
181 self.__sendCallTrace(event, frame, self.cFrame)
182 elif event == 'call':
183 self.__sendCallTrace(event, self.cFrame, frame)
184 self.cFrame = frame
185 self.__recursionDepth += 1
186 if self.__recursionDepth > gRecursionLimit:
187 raise RuntimeError(
188 'maximum recursion depth exceeded\n'
189 '(offending frame is two down the stack)')
190
191 def __sendCallTrace(self, event, fromFrame, toFrame):
192 """
193 Private method to send a call/return trace.
194
195 @param event trace event (string)
196 @param fromFrame originating frame (frame)
197 @param toFrame destination frame (frame)
198 """
199 if self._dbgClient.callTraceEnabled:
200 if not self.__skip_it(fromFrame) and not self.__skip_it(toFrame):
201 if event in ["call", "return"]:
202 fr = fromFrame
203 fromStr = "%s:%s:%s" % (
204 self._dbgClient.absPath(self.fix_frame_filename(fr)),
205 fr.f_lineno,
206 fr.f_code.co_name)
207 fr = toFrame
208 toStr = "%s:%s:%s" % (
209 self._dbgClient.absPath(self.fix_frame_filename(fr)),
210 fr.f_lineno,
211 fr.f_code.co_name)
212 self._dbgClient.write("%s%s@@%s@@%s\n" % (
213 CallTrace, event[0], fromStr, toStr))
214
215 def trace_dispatch(self, frame, event, arg):
216 """
217 Public method reimplemented from bdb.py to do some special things.
218
219 This specialty is to check the connection to the debug server
220 for new events (i.e. new breakpoints) while we are going through
221 the code.
222
223 @param frame The current stack frame.
224 @param event The trace event (string)
225 @param arg The arguments
226 @return local trace function
227 """
228 if self.quitting:
229 return # None
230
231 # give the client a chance to push through new break points.
232 self._dbgClient.eventPoll()
233
234 self.__event == event
235 self.__isBroken = False
236
237 if event == 'line':
238 return self.dispatch_line(frame)
239 if event == 'call':
240 return self.dispatch_call(frame, arg)
241 if event == 'return':
242 return self.dispatch_return(frame, arg)
243 if event == 'exception':
244 return self.dispatch_exception(frame, arg)
245 if event == 'c_call':
246 return self.trace_dispatch
247 if event == 'c_exception':
248 return self.trace_dispatch
249 if event == 'c_return':
250 return self.trace_dispatch
251 print 'DebugBase.trace_dispatch: unknown debugging event:', repr(event) # __IGNORE_WARNING__
252 return self.trace_dispatch
253
254 def dispatch_line(self, frame):
255 """
256 Public method reimplemented from bdb.py to do some special things.
257
258 This speciality is to check the connection to the debug server
259 for new events (i.e. new breakpoints) while we are going through
260 the code.
261
262 @param frame The current stack frame.
263 @return local trace function
264 @exception bdb.BdbQuit raised to indicate the end of the debug session
265 """
266 if self.stop_here(frame) or self.break_here(frame):
267 self.user_line(frame)
268 if self.quitting:
269 raise bdb.BdbQuit
270 return self.trace_dispatch
271
272 def dispatch_return(self, frame, arg):
273 """
274 Public method reimplemented from bdb.py to handle passive mode cleanly.
275
276 @param frame The current stack frame.
277 @param arg The arguments
278 @return local trace function
279 @exception bdb.BdbQuit raised to indicate the end of the debug session
280 """
281 if self.stop_here(frame) or frame == self.returnframe:
282 self.user_return(frame, arg)
283 if self.quitting and not self._dbgClient.passive:
284 raise bdb.BdbQuit
285 return self.trace_dispatch
286
287 def dispatch_exception(self, frame, arg):
288 """
289 Public method reimplemented from bdb.py to always call user_exception.
290
291 @param frame The current stack frame.
292 @param arg The arguments
293 @return local trace function
294 @exception bdb.BdbQuit raised to indicate the end of the debug session
295 """
296 if not self.__skip_it(frame):
297 self.user_exception(frame, arg)
298 if self.quitting:
299 raise bdb.BdbQuit
300 return self.trace_dispatch
301
302 def set_trace(self, frame=None):
303 """
304 Public method reimplemented from bdb.py to do some special setup.
305
306 @param frame frame to start debugging from
307 """
308 bdb.Bdb.set_trace(self, frame)
309 sys.setprofile(self.profile)
310
311 def set_continue(self, special):
312 """
313 Public method reimplemented from bdb.py to always get informed of
314 exceptions.
315
316 @param special flag indicating a special continue operation
317 """
318 # Modified version of the one found in bdb.py
319 # Here we only set a new stop frame if it is a normal continue.
320 if not special:
321 self.stopframe = self.botframe
322 self.returnframe = None
323 self.quitting = 0
324
325 def set_quit(self):
326 """
327 Public method to quit.
328
329 It wraps call to bdb to clear the current frame properly.
330 """
331 self.currentFrame = None
332 sys.setprofile(None)
333 bdb.Bdb.set_quit(self)
334
335 def fix_frame_filename(self, frame):
336 """
337 Public method used to fixup the filename for a given frame.
338
339 The logic employed here is that if a module was loaded
340 from a .pyc file, then the correct .py to operate with
341 should be in the same path as the .pyc. The reason this
342 logic is needed is that when a .pyc file is generated, the
343 filename embedded and thus what is readable in the code object
344 of the frame object is the fully qualified filepath when the
345 pyc is generated. If files are moved from machine to machine
346 this can break debugging as the .pyc will refer to the .py
347 on the original machine. Another case might be sharing
348 code over a network... This logic deals with that.
349
350 @param frame the frame object
351 @return fixed up file name (string)
352 """
353 # get module name from __file__
354 if '__file__' in frame.f_globals and \
355 frame.f_globals['__file__'] and \
356 frame.f_globals['__file__'] == frame.f_code.co_filename:
357 root, ext = os.path.splitext(frame.f_globals['__file__'])
358 if ext == '.pyc' or ext == '.py' or ext == '.pyo':
359 fixedName = root + '.py'
360 if os.path.exists(fixedName):
361 return fixedName
362
363 return frame.f_code.co_filename
364
365 def set_watch(self, cond, temporary=0):
366 """
367 Public method to set a watch expression.
368
369 @param cond expression of the watch expression (string)
370 @param temporary flag indicating a temporary watch expression (boolean)
371 """
372 bp = bdb.Breakpoint("Watch", 0, temporary, cond)
373 if cond.endswith('??created??') or cond.endswith('??changed??'):
374 bp.condition, bp.special = cond.split()
375 else:
376 bp.condition = cond
377 bp.special = ""
378 bp.values = {}
379 if "Watch" not in self.breaks:
380 self.breaks["Watch"] = 1
381 else:
382 self.breaks["Watch"] += 1
383
384 def clear_watch(self, cond):
385 """
386 Public method to clear a watch expression.
387
388 @param cond expression of the watch expression to be cleared (string)
389 """
390 try:
391 possibles = bdb.Breakpoint.bplist["Watch", 0]
392 for i in range(0, len(possibles)):
393 b = possibles[i]
394 if b.cond == cond:
395 b.deleteMe()
396 self.breaks["Watch"] -= 1
397 if self.breaks["Watch"] == 0:
398 del self.breaks["Watch"]
399 break
400 except KeyError:
401 pass
402
403 def get_watch(self, cond):
404 """
405 Public method to get a watch expression.
406
407 @param cond expression of the watch expression to be cleared (string)
408 @return reference to the watch point
409 """
410 possibles = bdb.Breakpoint.bplist["Watch", 0]
411 for i in range(0, len(possibles)):
412 b = possibles[i]
413 if b.cond == cond:
414 return b
415
416 def __do_clearWatch(self, cond):
417 """
418 Private method called to clear a temporary watch expression.
419
420 @param cond expression of the watch expression to be cleared (string)
421 """
422 self.clear_watch(cond)
423 self._dbgClient.write('%s%s\n' % (ResponseClearWatch, cond))
424
425 def __effective(self, frame):
426 """
427 Private method to determine, if a watch expression is effective.
428
429 @param frame the current execution frame
430 @return tuple of watch expression and a flag to indicate, that a
431 temporary watch expression may be deleted (bdb.Breakpoint, boolean)
432 """
433 possibles = bdb.Breakpoint.bplist["Watch", 0]
434 for i in range(0, len(possibles)):
435 b = possibles[i]
436 if b.enabled == 0:
437 continue
438 if not b.cond:
439 # watch expression without expression shouldn't occur,
440 # just ignore it
441 continue
442 try:
443 val = eval(b.condition, frame.f_globals, frame.f_locals)
444 if b.special:
445 if b.special == '??created??':
446 if b.values[frame][0] == 0:
447 b.values[frame][0] = 1
448 b.values[frame][1] = val
449 return (b, 1)
450 else:
451 continue
452 b.values[frame][0] = 1
453 if b.special == '??changed??':
454 if b.values[frame][1] != val:
455 b.values[frame][1] = val
456 if b.values[frame][2] > 0:
457 b.values[frame][2] -= 1
458 continue
459 else:
460 return (b, 1)
461 else:
462 continue
463 continue
464 if val:
465 if b.ignore > 0:
466 b.ignore -= 1
467 continue
468 else:
469 return (b, 1)
470 except Exception:
471 if b.special:
472 try:
473 b.values[frame][0] = 0
474 except KeyError:
475 b.values[frame] = [0, None, b.ignore]
476 continue
477 return (None, None)
478
479 def break_here(self, frame):
480 """
481 Public method reimplemented from bdb.py to fix the filename from the
482 frame.
483
484 See fix_frame_filename for more info.
485
486 @param frame the frame object
487 @return flag indicating the break status (boolean)
488 """
489 filename = self.canonic(self.fix_frame_filename(frame))
490 if filename not in self.breaks and "Watch" not in self.breaks:
491 return 0
492
493 if filename in self.breaks:
494 lineno = frame.f_lineno
495 if lineno in self.breaks[filename]:
496 # flag says ok to delete temp. bp
497 (bp, flag) = bdb.effective(filename, lineno, frame)
498 if bp:
499 self.currentbp = bp.number
500 if (flag and bp.temporary):
501 self.__do_clear(filename, lineno)
502 return 1
503
504 if "Watch" in self.breaks:
505 # flag says ok to delete temp. bp
506 (bp, flag) = self.__effective(frame)
507 if bp:
508 self.currentbp = bp.number
509 if (flag and bp.temporary):
510 self.__do_clearWatch(bp.cond)
511 return 1
512
513 return 0
514
515 def break_anywhere(self, frame):
516 """
517 Public method reimplemented from bdb.py to do some special things.
518
519 These speciality is to fix the filename from the frame
520 (see fix_frame_filename for more info).
521
522 @param frame the frame object
523 @return flag indicating the break status (boolean)
524 """
525 return \
526 self.canonic(self.fix_frame_filename(frame)) in self.breaks or \
527 ("Watch" in self.breaks and self.breaks["Watch"])
528
529 def get_break(self, filename, lineno):
530 """
531 Public method reimplemented from bdb.py to get the first breakpoint of
532 a particular line.
533
534 Because eric6 supports only one breakpoint per line, this overwritten
535 method will return this one and only breakpoint.
536
537 @param filename filename of the bp to retrieve (string)
538 @param lineno linenumber of the bp to retrieve (integer)
539 @return breakpoint or None, if there is no bp
540 """
541 filename = self.canonic(filename)
542 return filename in self.breaks and \
543 lineno in self.breaks[filename] and \
544 bdb.Breakpoint.bplist[filename, lineno][0] or None
545
546 def __do_clear(self, filename, lineno):
547 """
548 Private method called to clear a temporary breakpoint.
549
550 @param filename name of the file the bp belongs to
551 @param lineno linenumber of the bp
552 """
553 self.clear_break(filename, lineno)
554 self._dbgClient.write('%s%s,%d\n' % (ResponseClearBreak, filename,
555 lineno))
556
557 def getStack(self):
558 """
559 Public method to get the stack.
560
561 @return list of lists with file name (string), line number (integer)
562 and function name (string)
563 """
564 fr = self.cFrame
565 stack = []
566 while fr is not None:
567 fname = self._dbgClient.absPath(self.fix_frame_filename(fr))
568 if not fname.startswith("<"):
569 fline = fr.f_lineno
570 ffunc = fr.f_code.co_name
571
572 if ffunc == '?':
573 ffunc = ''
574
575 if ffunc and not ffunc.startswith("<"):
576 argInfo = inspect.getargvalues(fr)
577 try:
578 fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
579 argInfo[2], argInfo[3])
580 except Exception:
581 fargs = ""
582 else:
583 fargs = ""
584
585 stack.append([fname, fline, ffunc, fargs])
586
587 if fr == self._dbgClient.mainFrame:
588 fr = None
589 else:
590 fr = fr.f_back
591
592 return stack
593
594 def user_line(self, frame):
595 """
596 Public method reimplemented to handle the program about to execute a
597 particular line.
598
599 @param frame the frame object
600 """
601 line = frame.f_lineno
602
603 # We never stop on line 0.
604 if line == 0:
605 return
606
607 fn = self._dbgClient.absPath(self.fix_frame_filename(frame))
608
609 # See if we are skipping at the start of a newly loaded program.
610 if self._dbgClient.mainFrame is None:
611 if fn != self._dbgClient.getRunning():
612 return
613 fr = frame
614 while (fr is not None and
615 fr.f_code != self._dbgClient.handleLine.func_code):
616 self._dbgClient.mainFrame = fr
617 fr = fr.f_back
618
619 self.currentFrame = frame
620
621 fr = frame
622 stack = []
623 while fr is not None:
624 # Reset the trace function so we can be sure
625 # to trace all functions up the stack... This gets around
626 # problems where an exception/breakpoint has occurred
627 # but we had disabled tracing along the way via a None
628 # return from dispatch_call
629 fr.f_trace = self.trace_dispatch
630 fname = self._dbgClient.absPath(self.fix_frame_filename(fr))
631 if not fname.startswith("<"):
632 fline = fr.f_lineno
633 ffunc = fr.f_code.co_name
634
635 if ffunc == '?':
636 ffunc = ''
637
638 if ffunc and not ffunc.startswith("<"):
639 argInfo = inspect.getargvalues(fr)
640 try:
641 fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
642 argInfo[2], argInfo[3])
643 except Exception:
644 fargs = ""
645 else:
646 fargs = ""
647
648 stack.append([fname, fline, ffunc, fargs])
649
650 if fr == self._dbgClient.mainFrame:
651 fr = None
652 else:
653 fr = fr.f_back
654
655 self.__isBroken = True
656
657 self._dbgClient.write('%s%s\n' % (ResponseLine, unicode(stack)))
658 self._dbgClient.eventLoop()
659
660 def user_exception(self, frame, (exctype, excval, exctb), unhandled=0):
661 """
662 Public method reimplemented to report an exception to the debug server.
663
664 @param frame the frame object
665 @param exctype the type of the exception
666 @param excval data about the exception
667 @param exctb traceback for the exception
668 @param unhandled flag indicating an uncaught exception
669 """
670 if exctype in [GeneratorExit, StopIteration]:
671 # ignore these
672 return
673
674 if exctype in [SystemExit, bdb.BdbQuit]:
675 atexit._run_exitfuncs()
676 if excval is None:
677 excval = 0
678 elif isinstance(excval, (unicode, str)):
679 self._dbgClient.write(excval)
680 excval = 1
681 if isinstance(excval, int):
682 self._dbgClient.progTerminated(excval)
683 else:
684 self._dbgClient.progTerminated(excval.code)
685 return
686
687 if exctype in [SyntaxError, IndentationError]:
688 try:
689 message, (filename, linenr, charnr, text) = excval
690 except ValueError:
691 exclist = []
692 realSyntaxError = True
693 else:
694 exclist = [message, [filename, linenr, charnr]]
695 realSyntaxError = os.path.exists(filename)
696
697 if realSyntaxError:
698 self._dbgClient.write("%s%s\n" % (ResponseSyntax,
699 unicode(exclist)))
700 self._dbgClient.eventLoop()
701 return
702
703 if type(exctype) in [types.ClassType, # Python up to 2.4
704 types.TypeType]: # Python 2.5+
705 exctype = exctype.__name__
706
707 if excval is None:
708 excval = ''
709
710 if unhandled:
711 exctypetxt = "unhandled %s" % unicode(exctype)
712 else:
713 exctypetxt = unicode(exctype)
714 try:
715 exclist = [exctypetxt,
716 unicode(excval).encode(self._dbgClient.getCoding())]
717 except TypeError:
718 exclist = [exctypetxt, str(excval)]
719
720 if exctb:
721 frlist = self.__extract_stack(exctb)
722 frlist.reverse()
723
724 self.currentFrame = frlist[0]
725
726 for fr in frlist:
727 filename = self._dbgClient.absPath(self.fix_frame_filename(fr))
728
729 if os.path.basename(filename).startswith("DebugClient") or \
730 os.path.basename(filename) == "bdb.py":
731 break
732
733 linenr = fr.f_lineno
734 ffunc = fr.f_code.co_name
735
736 if ffunc == '?':
737 ffunc = ''
738
739 if ffunc and not ffunc.startswith("<"):
740 argInfo = inspect.getargvalues(fr)
741 try:
742 fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
743 argInfo[2], argInfo[3])
744 except Exception:
745 fargs = ""
746 else:
747 fargs = ""
748
749 exclist.append([filename, linenr, ffunc, fargs])
750
751 self._dbgClient.write("%s%s\n" % (ResponseException, unicode(exclist)))
752
753 if exctb is None:
754 return
755
756 self._dbgClient.eventLoop()
757
758 def __extract_stack(self, exctb):
759 """
760 Private member to return a list of stack frames.
761
762 @param exctb exception traceback
763 @return list of stack frames
764 """
765 tb = exctb
766 stack = []
767 while tb is not None:
768 stack.append(tb.tb_frame)
769 tb = tb.tb_next
770 tb = None
771 return stack
772
773 def user_return(self, frame, retval):
774 """
775 Public method reimplemented to report program termination to the
776 debug server.
777
778 @param frame the frame object
779 @param retval the return value of the program
780 """
781 # The program has finished if we have just left the first frame.
782 if frame == self._dbgClient.mainFrame and \
783 self._mainThread:
784 atexit._run_exitfuncs()
785 self._dbgClient.progTerminated(retval)
786 elif frame is not self.stepFrame:
787 self.stepFrame = None
788 self.user_line(frame)
789
790 def stop_here(self, frame):
791 """
792 Public method reimplemented to filter out debugger files.
793
794 Tracing is turned off for files that are part of the
795 debugger that are called from the application being debugged.
796
797 @param frame the frame object
798 @return flag indicating whether the debugger should stop here
799 """
800 if self.__skip_it(frame):
801 return 0
802 return bdb.Bdb.stop_here(self, frame)
803
804 def __skip_it(self, frame):
805 """
806 Private method to filter out debugger files.
807
808 Tracing is turned off for files that are part of the
809 debugger that are called from the application being debugged.
810
811 @param frame the frame object
812 @return flag indicating whether the debugger should skip this frame
813 """
814 if frame is None:
815 return 1
816
817 fn = self.fix_frame_filename(frame)
818
819 # Eliminate things like <string> and <stdin>.
820 if fn[0] == '<':
821 return 1
822
823 #XXX - think of a better way to do this. It's only a convenience for
824 #debugging the debugger - when the debugger code is in the current
825 #directory.
826 if os.path.basename(fn) in [
827 'AsyncFile.py', 'AsyncIO.py',
828 'DebugConfig.py', 'DCTestResult.py',
829 'DebugBase.py', 'DebugClientBase.py',
830 'DebugClientCapabilities.py', 'DebugClient.py',
831 'DebugClientThreads.py', 'DebugProtocol.py',
832 'DebugThread.py', 'FlexCompleter.py',
833 'PyProfile.py'] or \
834 os.path.dirname(fn).endswith("coverage"):
835 return 1
836
837 if self._dbgClient.shouldSkip(fn):
838 return 1
839
840 return 0
841
842 def isBroken(self):
843 """
844 Public method to return the broken state of the debugger.
845
846 @return flag indicating the broken state (boolean)
847 """
848 return self.__isBroken
849
850 def getEvent(self):
851 """
852 Protected method to return the last debugger event.
853
854 @return last debugger event (string)
855 """
856 return self.__event
857
858 #
859 # eflag: FileType = Python2
860 # eflag: noqa = M601, M702

eric ide

mercurial