From 3e62b1aee597694df204c23971c91c13924afa75 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 28 Aug 2015 12:22:30 +0300 Subject: [PATCH] Yet another updates and optimizations from PyDev.Debugger --- python/helpers/pydev/pydevd.py | 50 ++++++++++------------ python/helpers/pydev/pydevd_breakpoints.py | 8 ++-- python/helpers/pydev/pydevd_signature.py | 10 +---- python/helpers/pydev/pydevd_utils.py | 35 +++++++++++++-- 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index c149a45f197f..7dbb6d8cde9f 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -3,6 +3,7 @@ from __future__ import nested_scopes # Jython 2.1 support import pydev_monkey_qt from pydevd_utils import save_main_module +import pydevd_utils pydev_monkey_qt.patch_qt() @@ -28,7 +29,7 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \ CMD_STEP_OVER, \ CMD_STEP_RETURN, \ CMD_STEP_INTO_MY_CODE, \ - CMD_THREAD_KILL, \ + CMD_THREAD_KILL, \ CMD_THREAD_RUN, \ CMD_THREAD_SUSPEND, \ CMD_RUN_TO_LINE, \ @@ -51,7 +52,7 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \ InternalTerminateThread, \ InternalRunThread, \ InternalStepThread, \ - NetCommandFactory, \ + NetCommandFactory, \ PyDBDaemonThread, \ _queue, \ ReaderThread, \ @@ -63,15 +64,18 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \ StartServer, \ InternalSetNextStatementThread, \ ReloadCodeCommand, \ - CMD_SET_PY_EXCEPTION, \ + CMD_SET_PY_EXCEPTION, \ CMD_IGNORE_THROWN_EXCEPTION_AT,\ InternalGetBreakpointException, \ InternalSendCurrExceptionTrace,\ InternalSendCurrExceptionTraceProceeded,\ CMD_ENABLE_DONT_TRACE, \ CMD_GET_FILE_CONTENTS,\ - CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\ - InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\ + CMD_SET_PROPERTY_TRACE, \ + CMD_RUN_CUSTOM_OPERATION,\ + InternalRunCustomOperation, \ + CMD_EVALUATE_CONSOLE_EXPRESSION, \ + InternalEvaluateConsoleExpression,\ InternalConsoleGetCompletions from pydevd_file_utils import NormFileToServer, GetFilenameAndBase @@ -194,14 +198,14 @@ if hasattr(_temp, '_is_stopped'): # Python 3.4 has this return not t._is_stopped except: return t.isAlive() - + elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this def isThreadAlive(t): try: return not t._Thread__stopped except: return t.isAlive() - + else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case. def isThreadAlive(t): return t.isAlive() @@ -378,26 +382,16 @@ class PyDB: self.mpl_in_use = False self.mpl_hooks_in_debug_console = False self.mpl_modules_for_patching = {} + + self._filename_to_not_in_scope = {} def get_plugin_lazy_init(self): if self.plugin is None and SUPPORT_PLUGINS: self.plugin = PluginManager(self) return self.plugin - def get_project_roots(self): - if self.project_roots is None: - roots = os.getenv('IDE_PROJECT_ROOTS', '').split(os.pathsep) - pydev_log.debug("IDE_PROJECT_ROOTS %s\n" % roots) - self.project_roots = roots - def not_in_scope(self, filename): - self.get_project_roots() - filename = os.path.normcase(filename) - for root in self.project_roots: - root = os.path.normcase(root) - if filename.startswith(root): - return False - return True + return pydevd_utils.is_in_project_roots(filename) def first_appearance_in_scope(self, trace): if trace is None or self.not_in_scope(trace.tb_frame.f_code.co_filename): @@ -1217,10 +1211,10 @@ class PyDB: update_exception_hook(self) else: supported_type = False - + # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). - plugin = self.plugin + plugin = self.plugin if plugin is not None: supported_type = plugin.remove_exception_breakpoint(self, type, exception) @@ -2078,15 +2072,15 @@ def stoptrace(): from pydev_monkey import undo_patch_thread_modules undo_patch_thread_modules() - + debugger = GetGlobalDebugger() - + if debugger: - + debugger.SetTraceForFrameAndParents( GetFrame(), also_add_to_passed_frame=True, overwrite_prev_trace=True, dispatch_func=lambda *args:None) debugger.exiting() - + killAllPydevThreads() connected = False @@ -2118,7 +2112,7 @@ class DispatchReader(ReaderThread): dummy_thread = threading.currentThread() dummy_thread.is_pydev_daemon_thread = False return ReaderThread.OnRun(self) - + def handleExcept(self): ReaderThread.handleExcept(self) @@ -2182,7 +2176,7 @@ class SetupHolder: # main #======================================================================================================================= if __name__ == '__main__': - + # parse the command line. --file is our last argument that is required try: sys.original_argv = sys.argv[:] diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py index fdd069abcd1e..c349ccd1a70b 100644 --- a/python/helpers/pydev/pydevd_breakpoints.py +++ b/python/helpers/pydev/pydevd_breakpoints.py @@ -96,19 +96,19 @@ def _excepthook(exctype, value, tb): frames = [] debugger = GetGlobalDebugger() - user_frames = [] + user_frame = None while tb: frame = tb.tb_frame if exception_breakpoint.ignore_libraries and not debugger.not_in_scope(frame.f_code.co_filename): - user_frames.append(tb.tb_frame) + user_frame = tb.tb_frame frames.append(tb.tb_frame) tb = tb.tb_next thread = threadingCurrentThread() frames_byid = dict([(id(frame),frame) for frame in frames]) - if exception_breakpoint.ignore_libraries: - frame = user_frames[-1] + if exception_breakpoint.ignore_libraries and user_frame is not None: + frame = user_frame else: frame = frames[-1] thread.additionalInfo.exception = (exctype, value, tb) diff --git a/python/helpers/pydev/pydevd_signature.py b/python/helpers/pydev/pydevd_signature.py index 5967ab31786e..a37901214f23 100644 --- a/python/helpers/pydev/pydevd_signature.py +++ b/python/helpers/pydev/pydevd_signature.py @@ -31,17 +31,9 @@ class Signature(object): class SignatureFactory(object): def __init__(self): self._caller_cache = {} - self.project_roots = os.getenv('IDE_PROJECT_ROOTS', '').split(os.pathsep) def is_in_scope(self, filename): - filename = os.path.normcase(filename) - for root in self.project_roots: - root = os.path.normcase(root) - if filename.startswith(root): - return True - return False - - + return pydevd_utils.is_in_project_roots(filename) def create_signature(self, frame): try: diff --git a/python/helpers/pydev/pydevd_utils.py b/python/helpers/pydev/pydevd_utils.py index 054dd69327d5..34fc24cf37b0 100644 --- a/python/helpers/pydev/pydevd_utils.py +++ b/python/helpers/pydev/pydevd_utils.py @@ -5,9 +5,10 @@ try: except: from urllib.parse import quote +import os import pydevd_constants import sys - +import pydev_log def save_main_module(file, module_name): # patch provided by: Scott Schlesier - when script is run, it does not @@ -113,7 +114,35 @@ def quote_smart(s, safe='/'): s = s.encode('utf-8') return quote(s, safe) - - + + +def _get_project_roots(project_roots_cache=[]): + # Note: the project_roots_cache is the same instance among the many calls to the method + if not project_roots_cache: + roots = os.getenv('IDE_PROJECT_ROOTS', '').split(os.pathsep) + pydev_log.debug("IDE_PROJECT_ROOTS %s\n" % roots) + new_roots = [] + for root in roots: + new_roots.append(os.path.normcase(root)) + project_roots_cache.append(new_roots) + return project_roots_cache[-1] # returns the project roots with case normalized + + +def is_in_project_roots(filename, filename_to_not_in_scope_cache={}): + # Note: the filename_to_not_in_scope_cache is the same instance among the many calls to the method + try: + return filename_to_not_in_scope_cache[filename] + except: + project_roots = _get_project_roots() + filename = os.path.normcase(filename) + for root in project_roots: + if filename.startswith(root): + filename_to_not_in_scope_cache[filename] = False + break + else: # for else (only called if the break wasn't reached). + filename_to_not_in_scope_cache[filename] = True + + # at this point it must be loaded. + return filename_to_not_in_scope_cache[filename]