46 Class implementing base class of the debugger. |
46 Class implementing base class of the debugger. |
47 |
47 |
48 Provides simple wrapper methods around bdb for the 'owning' client to |
48 Provides simple wrapper methods around bdb for the 'owning' client to |
49 call to step etc. |
49 call to step etc. |
50 """ |
50 """ |
|
51 # Don't thrust distutils.sysconfig.get_python_lib: possible case mismatch |
|
52 # on Windows |
|
53 lib = os.path.dirname(bdb.__file__) |
|
54 # tuple required because it's accessed a lot of times by startswith method |
|
55 pathsToSkip = ('<', os.path.dirname(__file__), bdb.__file__[:-1]) |
|
56 filesToSkip = {} |
|
57 |
51 def __init__(self, dbgClient): |
58 def __init__(self, dbgClient): |
52 """ |
59 """ |
53 Constructor |
60 Constructor |
54 |
61 |
55 @param dbgClient the owning client |
62 @param dbgClient the owning client |
195 @param event trace event (string) |
203 @param event trace event (string) |
196 @param fromFrame originating frame (frame) |
204 @param fromFrame originating frame (frame) |
197 @param toFrame destination frame (frame) |
205 @param toFrame destination frame (frame) |
198 """ |
206 """ |
199 if self._dbgClient.callTraceEnabled: |
207 if self._dbgClient.callTraceEnabled: |
200 if not self.__skip_it(fromFrame) and not self.__skip_it(toFrame): |
208 if (not self.__skipFrame(fromFrame) and |
|
209 not self.__skipFrame(toFrame)): |
201 if event in ["call", "return"]: |
210 if event in ["call", "return"]: |
202 fr = fromFrame |
211 fr = fromFrame |
203 fromStr = "%s:%s:%s" % ( |
212 fromStr = "%s:%s:%s" % ( |
204 self._dbgClient.absPath(self.fix_frame_filename(fr)), |
213 self._dbgClient.absPath(self.fix_frame_filename(fr)), |
205 fr.f_lineno, |
214 fr.f_lineno, |
246 return self.trace_dispatch |
255 return self.trace_dispatch |
247 if event == 'c_exception': |
256 if event == 'c_exception': |
248 return self.trace_dispatch |
257 return self.trace_dispatch |
249 if event == 'c_return': |
258 if event == 'c_return': |
250 return self.trace_dispatch |
259 return self.trace_dispatch |
251 print 'DebugBase.trace_dispatch: unknown debugging event:', repr(event) # __IGNORE_WARNING__ |
260 print 'DebugBase.trace_dispatch: unknown debugging event:', repr(event) # __IGNORE_WARNING__ |
252 return self.trace_dispatch |
261 return self.trace_dispatch |
253 |
262 |
254 def dispatch_line(self, frame): |
263 def dispatch_line(self, frame): |
255 """ |
264 """ |
256 Public method reimplemented from bdb.py to do some special things. |
265 Public method reimplemented from bdb.py to do some special things. |
291 @param frame The current stack frame. |
300 @param frame The current stack frame. |
292 @param arg The arguments |
301 @param arg The arguments |
293 @return local trace function |
302 @return local trace function |
294 @exception bdb.BdbQuit raised to indicate the end of the debug session |
303 @exception bdb.BdbQuit raised to indicate the end of the debug session |
295 """ |
304 """ |
296 if not self.__skip_it(frame): |
305 if not self.__skipFrame(frame): |
297 self.user_exception(frame, arg) |
306 self.user_exception(frame, arg) |
298 if self.quitting: |
307 if self.quitting: |
299 raise bdb.BdbQuit |
308 raise bdb.BdbQuit |
300 return self.trace_dispatch |
309 return self.trace_dispatch |
301 |
310 |
532 a particular line. |
541 a particular line. |
533 |
542 |
534 Because eric6 supports only one breakpoint per line, this overwritten |
543 Because eric6 supports only one breakpoint per line, this overwritten |
535 method will return this one and only breakpoint. |
544 method will return this one and only breakpoint. |
536 |
545 |
537 @param filename filename of the bp to retrieve (string) |
546 @param filename the filename of the bp to retrieve (string) |
538 @param lineno linenumber of the bp to retrieve (integer) |
547 @param lineno the linenumber of the bp to retrieve (integer) |
539 @return breakpoint or None, if there is no bp |
548 @return breakpoint or None, if there is no bp |
540 """ |
549 """ |
541 filename = self.canonic(filename) |
550 filename = self.canonic(filename) |
542 return filename in self.breaks and \ |
551 return filename in self.breaks and \ |
543 lineno in self.breaks[filename] and \ |
552 lineno in self.breaks[filename] and \ |
795 debugger that are called from the application being debugged. |
804 debugger that are called from the application being debugged. |
796 |
805 |
797 @param frame the frame object |
806 @param frame the frame object |
798 @return flag indicating whether the debugger should stop here |
807 @return flag indicating whether the debugger should stop here |
799 """ |
808 """ |
800 if self.__skip_it(frame): |
809 if self.__skipFrame(frame): |
801 return 0 |
810 return 0 |
802 return bdb.Bdb.stop_here(self, frame) |
811 return bdb.Bdb.stop_here(self, frame) |
803 |
812 |
804 def __skip_it(self, frame): |
813 def tracePythonLibs(self, enable): |
|
814 """ |
|
815 Public methode to update the settings to trace into Python libraries. |
|
816 |
|
817 @param enable let's debug into Python libraries (int) |
|
818 """ |
|
819 pathsToSkip = list(self.pathsToSkip) |
|
820 # don't trace into Python library? |
|
821 if enable: |
|
822 pathsToSkip = [x for x in pathsToSkip if not x.endswith( |
|
823 ("site-packages", "dist-packages", self.lib))] |
|
824 else: |
|
825 pathsToSkip.append(self.lib) |
|
826 localLib = [x for x in sys.path if x.endswith(("site-packages", |
|
827 "dist-packages")) and not x.startswith(self.lib)] |
|
828 pathsToSkip.extend(localLib) |
|
829 |
|
830 self.pathsToSkip = tuple(pathsToSkip) |
|
831 |
|
832 def __skipFrame(self, frame): |
805 """ |
833 """ |
806 Private method to filter out debugger files. |
834 Private method to filter out debugger files. |
807 |
835 |
808 Tracing is turned off for files that are part of the |
836 Tracing is turned off for files that are part of the |
809 debugger that are called from the application being debugged. |
837 debugger that are called from the application being debugged. |
810 |
838 |
811 @param frame the frame object |
839 @param frame the frame object |
812 @return flag indicating whether the debugger should skip this frame |
840 @return flag indicating whether the debugger should skip this frame |
813 """ |
841 """ |
814 if frame is None: |
842 try: |
815 return 1 |
843 return self.filesToSkip[frame.f_code.co_filename] |
816 |
844 except KeyError: |
817 fn = self.fix_frame_filename(frame) |
845 ret = frame.f_code.co_filename.startswith(self.pathsToSkip) |
818 |
846 self.filesToSkip[frame.f_code.co_filename] = ret |
819 # Eliminate things like <string> and <stdin>. |
847 return ret |
820 if fn[0] == '<': |
848 except AttributeError: |
821 return 1 |
849 # if frame is None |
822 |
850 return True |
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 |
851 |
842 def isBroken(self): |
852 def isBroken(self): |
843 """ |
853 """ |
844 Public method to return the broken state of the debugger. |
854 Public method to return the broken state of the debugger. |
845 |
855 |