diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 03bc80596148..c5e513d768c3 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -342,6 +342,7 @@ class PyDB: self.SetTrace = pydevd_tracing.SetTrace self.break_on_exceptions_thrown_in_same_context = False self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True + self.project_roots = None # Suspend debugger even if breakpoint condition raises an exception SUSPEND_ON_BREAKPOINT_EXCEPTION = True @@ -375,6 +376,15 @@ class PyDB: self.plugin = PluginManager(self) return self.plugin + def not_in_scope(self, filename): + if self.project_roots is None: + return False + filename = os.path.normcase(filename) + for root in self.project_roots: + root = os.path.normcase(root) + if filename.startswith(root): + return False + return True def haveAliveThreads(self): for t in threadingEnumerate(): @@ -632,6 +642,7 @@ class PyDB: notify_always, notify_on_terminate, notify_on_first_raise_only, + ignore_libraries ): try: eb = ExceptionBreakpoint( @@ -639,6 +650,7 @@ class PyDB: notify_always, notify_on_terminate, notify_on_first_raise_only, + ignore_libraries ) except ImportError: pydev_log.error("Error unable to add break on exception for: %s (exception could not be imported)\n" % (exception,)) @@ -1116,9 +1128,12 @@ class PyDB: elif cmd_id == CMD_ADD_EXCEPTION_BREAK: if text.find('\t') != -1: - exception, notify_always, notify_on_terminate = text.split('\t', 2) + exception, notify_always, notify_on_terminate, ignore_libraries = text.split('\t', 3) else: - exception, notify_always, notify_on_terminate = text, 0, 0 + exception, notify_always, notify_on_terminate, ignore_libraries = text, 0, 0, 0 + + if ignore_libraries > 0 and self.project_roots is None: + self.project_roots = os.getenv('PYCHARM_PROJECT_ROOTS', '').split(os.pathsep) if exception.find('-') != -1: type, exception = exception.split('-') @@ -1130,7 +1145,8 @@ class PyDB: exception, notify_always=int(notify_always) > 0, notify_on_terminate = int(notify_on_terminate) == 1, - notify_on_first_raise_only=int(notify_always) == 2 + notify_on_first_raise_only=int(notify_always) == 2, + ignore_libraries=int(ignore_libraries) > 0 ) if exception_breakpoint is not None: diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py index 693823917a2f..ab8550f28998 100644 --- a/python/helpers/pydev/pydevd_breakpoints.py +++ b/python/helpers/pydev/pydevd_breakpoints.py @@ -22,6 +22,7 @@ class ExceptionBreakpoint: notify_always, notify_on_terminate, notify_on_first_raise_only, + ignore_libraries ): exctype = _get_class(qname) self.qname = qname @@ -33,6 +34,7 @@ class ExceptionBreakpoint: self.notify_on_terminate = notify_on_terminate self.notify_always = notify_always self.notify_on_first_raise_only = notify_on_first_raise_only + self.ignore_libraries = ignore_libraries self.type = exctype diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py index 1417ee2c8308..c2e2f6caac98 100644 --- a/python/helpers/pydev/pydevd_frame.py +++ b/python/helpers/pydev/pydevd_frame.py @@ -76,6 +76,10 @@ class PyDBFrame: if exception_breakpoint is not None: if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace): # print frame.f_code.co_name + if exception_breakpoint.ignore_libraries: + if mainDebugger.not_in_scope(frame.f_code.co_filename): + return False, frame + add_exception_to_frame(frame, (exception, value, trace)) thread.additionalInfo.message = exception_breakpoint.qname flag = True @@ -87,7 +91,6 @@ class PyDBFrame: result = mainDebugger.plugin.exception_break(mainDebugger, self, frame, self._args, arg) if result: (flag, frame) = result - except: flag = False diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AddExceptionBreakpointCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AddExceptionBreakpointCommand.java index aa014da5df79..b79a220b26d5 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AddExceptionBreakpointCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AddExceptionBreakpointCommand.java @@ -18,18 +18,22 @@ public class AddExceptionBreakpointCommand extends ExceptionBreakpointCommand { protected void buildPayload(Payload payload) { super.buildPayload(payload); payload.add(myNotifyPolicy.isNotifyAlways() ? 1 : myNotifyPolicy.isNotifyOnlyOnFirst() ? 2 : 0) - .add(myNotifyPolicy.isNotifyOnTerminate()); + .add(myNotifyPolicy.isNotifyOnTerminate()) + .add(myNotifyPolicy.isIgnoreLibraries()); } public static class ExceptionBreakpointNotifyPolicy { private final boolean myNotifyAlways; private final boolean myNotifyOnTerminate; private final boolean myNotifyOnlyOnFirst; + private final boolean myIgnoreLibraries; - public ExceptionBreakpointNotifyPolicy(boolean notifyAlways, boolean notifyOnTerminate, boolean notifyOnlyOnFirst) { + public ExceptionBreakpointNotifyPolicy(boolean notifyAlways, boolean notifyOnTerminate, boolean notifyOnlyOnFirst, + boolean ignoreLibraries) { myNotifyAlways = notifyAlways; myNotifyOnTerminate = notifyOnTerminate; myNotifyOnlyOnFirst = notifyOnlyOnFirst; + myIgnoreLibraries = ignoreLibraries; } public boolean isNotifyAlways() { @@ -43,5 +47,9 @@ public class AddExceptionBreakpointCommand extends ExceptionBreakpointCommand { public boolean isNotifyOnlyOnFirst() { return myNotifyOnlyOnFirst; } + + public boolean isIgnoreLibraries() { + return myIgnoreLibraries; + } } } diff --git a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java index 553223d9d3df..d0628db29c52 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java @@ -224,13 +224,14 @@ public class PyDebugRunner extends GenericProgramRunner { if (PyDebuggerOptionsProvider.getInstance(project).isSaveCallSignatures()) { debugParams.addParameter("--save-signatures"); - addProjectRootsToEnv(project, generalCommandLine); } if (PyDebuggerOptionsProvider.getInstance(project).isSupportGeventDebugging()) { generalCommandLine.getEnvironment().put(GEVENT_SUPPORT, "True"); } + addProjectRootsToEnv(project, generalCommandLine); + final String[] debuggerArgs = new String[]{ CLIENT_PARAM, "127.0.0.1", PORT_PARAM, String.valueOf(serverLocalPort), diff --git a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java index 34c82098fef2..811f91f1f727 100644 --- a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java +++ b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java @@ -31,6 +31,8 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti public boolean myNotifyOnlyOnFirst; @Attribute("notifyOnTerminate") public boolean myNotifyOnTerminate; + @Attribute("ignoreLibraries") + public boolean myIgnoreLibraries; @SuppressWarnings({"UnusedDeclaration"}) @@ -40,6 +42,7 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti public PyExceptionBreakpointProperties(@NotNull final String exception) { myException = exception; myNotifyOnTerminate = true; + myIgnoreLibraries = true; } @Override @@ -53,6 +56,7 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti myNotifyAlways = state.myNotifyAlways; myNotifyOnlyOnFirst = state.myNotifyOnlyOnFirst; myNotifyOnTerminate = state.myNotifyOnTerminate; + myIgnoreLibraries = state.myIgnoreLibraries; } public boolean isNotifyOnTerminate() { @@ -79,6 +83,14 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti myNotifyOnlyOnFirst = notifyOnlyOnFirst; } + public void setIgnoreLibraries(boolean ignoreLibraries) { + myIgnoreLibraries = ignoreLibraries; + } + + public boolean isIgnoreLibraries() { + return myIgnoreLibraries; + } + public String getExceptionBreakpointId() { return "python-" + myException; } @@ -88,7 +100,7 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti return ExceptionBreakpointCommand.addExceptionBreakpointCommand(debugger, getExceptionBreakpointId(), new AddExceptionBreakpointCommand.ExceptionBreakpointNotifyPolicy( isNotifyAlways(), - isNotifyOnTerminate(), isNotifyOnlyOnFirst())); + isNotifyOnTerminate(), isNotifyOnlyOnFirst(), isIgnoreLibraries())); } @Override diff --git a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointType.java b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointType.java index 12bde3d60aea..4b06475ad718 100644 --- a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointType.java +++ b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointType.java @@ -168,6 +168,7 @@ public class PyExceptionBreakpointType private static class PyExceptionBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel> { + private JCheckBox myIgnoreLibrariesCheckBox; private JCheckBox myNotifyOnTerminateCheckBox; private JCheckBox myNotifyOnRaiseCheckBox; private JRadioButton myAlwaysRadio; @@ -176,6 +177,7 @@ public class PyExceptionBreakpointType @NotNull @Override public JComponent getComponent() { + myIgnoreLibrariesCheckBox = new JCheckBox("Ignore library files"); myNotifyOnTerminateCheckBox = new JCheckBox("On termination"); myNotifyOnRaiseCheckBox = new JCheckBox("On raise"); myAlwaysRadio = new JRadioButton("At each level of call chain"); @@ -187,6 +189,9 @@ public class PyExceptionBreakpointType Box notificationsBox = Box.createVerticalBox(); JPanel panel = new JPanel(new BorderLayout()); + panel.add(myIgnoreLibrariesCheckBox, BorderLayout.NORTH); + notificationsBox.add(panel); + panel = new JPanel(new BorderLayout()); panel.add(myNotifyOnTerminateCheckBox, BorderLayout.NORTH); notificationsBox.add(panel); panel = new JPanel(new BorderLayout()); @@ -243,6 +248,7 @@ public class PyExceptionBreakpointType @Override public void saveTo(@NotNull XBreakpoint breakpoint) { + breakpoint.getProperties().setIgnoreLibraries(myIgnoreLibrariesCheckBox.isSelected()); breakpoint.getProperties().setNotifyOnTerminate(myNotifyOnTerminateCheckBox.isSelected()); breakpoint.getProperties().setNotifyAlways(myNotifyOnRaiseCheckBox.isSelected() && myAlwaysRadio.isSelected()); @@ -251,6 +257,7 @@ public class PyExceptionBreakpointType @Override public void loadFrom(@NotNull XBreakpoint breakpoint) { + myIgnoreLibrariesCheckBox.setSelected(breakpoint.getProperties().isIgnoreLibraries()); myNotifyOnTerminateCheckBox.setSelected(breakpoint.getProperties().isNotifyOnTerminate()); boolean always = breakpoint.getProperties().isNotifyAlways();