diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py index d66c72c4e346..7ce1af7ecf5b 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py @@ -1057,8 +1057,10 @@ class InternalGetFrame(InternalThreadCommand): try: frame = pydevd_vars.find_frame(self.thread_id, self.frame_id) if frame is not None: + hidden_ns = pydevconsole.get_ipython_hidden_vars_dict() xml = "" xml += pydevd_xml.frame_vars_to_xml(frame.f_locals) + xml += pydevd_vars.frame_vars_to_xml(frame.f_locals, hidden_ns) del frame xml += "" cmd = dbg.cmd_factory.make_get_frame_message(self.sequence, xml) diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_xml.py b/python/helpers/pydev/_pydevd_bundle/pydevd_xml.py index 7c1a87b3c891..35c6c242288c 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_xml.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_xml.py @@ -162,7 +162,16 @@ def return_values_from_dict_to_xml(return_dict): return res -def frame_vars_to_xml(frame_f_locals): +def ipython_hidden_values_to_xml(key, val, hidden_ns): + res = "" + if key in hidden_ns.keys(): + res += var_to_xml(val, str(key), ipython_hidden=True) + else: + res += var_to_xml(val, str(key)) + return res + + +def frame_vars_to_xml(frame_f_locals, hidden_ns=None): """ dumps frame variables to XML """ @@ -180,7 +189,10 @@ def frame_vars_to_xml(frame_f_locals): if k == RETURN_VALUES_DICT: xml += return_values_from_dict_to_xml(v) else: - xml += var_to_xml(v, str(k)) + if hidden_ns is not None: + xml += ipython_hidden_values_to_xml(k, v, hidden_ns) + else: + xml += var_to_xml(v, str(k)) except Exception: traceback.print_exc() pydev_log.error("Unexpected error, recovered safely.\n") @@ -191,7 +203,7 @@ def frame_vars_to_xml(frame_f_locals): def get_type_qualifier(type): return getattr(type, "__module__", "") -def var_to_xml(val, name, doTrim=True, additionalInXml='', return_value=False): +def var_to_xml(val, name, doTrim=True, additionalInXml='', return_value=False, ipython_hidden=False): """ single variable or dictionary to xml representation """ is_exception_on_eval = isinstance(val, ExceptionOnEvaluate) @@ -256,6 +268,11 @@ def var_to_xml(val, name, doTrim=True, additionalInXml='', return_value=False): else: xmlRetVal = '' + if ipython_hidden: + xmlIPythonHidden = ' isIPythonHidden="True"' + else: + xmlIPythonHidden = '' + xml = '\n')) + return ''.join((xml, xmlQualifier, xmlValue, xmlCont, xmlRetVal, xmlIPythonHidden, additionalInXml, ' />\n')) diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index aa0f44107e42..05a2584b3c71 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -355,6 +355,18 @@ def start_server(host, port, client_port): process_exec_queue(interpreter) +def get_ipython_hidden_vars_dict(): + try: + if IPYTHON and hasattr(__builtin__, 'interpreter'): + pydev_interpreter = get_interpreter().interpreter + if hasattr(pydev_interpreter, 'ipython') and hasattr(pydev_interpreter.ipython, 'user_ns_hidden'): + return pydev_interpreter.ipython.user_ns_hidden + return None + except Exception: + traceback.print_exc() + return None + + def get_interpreter(): try: interpreterInterface = getattr(__builtin__, 'interpreter') diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java index d4191713c53a..5737592904ed 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java @@ -27,6 +27,7 @@ public class PyDebugValue extends XNamedValue { private final String myValue; private final boolean myContainer; private final boolean myIsReturnedVal; + private final boolean myIsIPythonHidden; private final PyDebugValue myParent; private String myId = null; @@ -37,18 +38,20 @@ public class PyDebugValue extends XNamedValue { private final boolean myErrorOnEval; public PyDebugValue(@NotNull final String name, final String type, String typeQualifier, final String value, final boolean container, - boolean isReturnedVal, boolean errorOnEval, final PyFrameAccessor frameAccessor) { - this(name, type, typeQualifier, value, container, isReturnedVal, errorOnEval, null, frameAccessor); + boolean isReturnedVal, boolean isIPythonHidden, boolean errorOnEval, final PyFrameAccessor frameAccessor) { + this(name, type, typeQualifier, value, container, isReturnedVal, isIPythonHidden, errorOnEval, null, frameAccessor); } public PyDebugValue(@NotNull final String name, final String type, String typeQualifier, final String value, final boolean container, - boolean isReturnedVal, boolean errorOnEval, final PyDebugValue parent, final PyFrameAccessor frameAccessor) { + boolean isReturnedVal, boolean isIPythonHidden, boolean errorOnEval, final PyDebugValue parent, + final PyFrameAccessor frameAccessor) { super(name); myType = type; myTypeQualifier = Strings.isNullOrEmpty(typeQualifier) ? null : typeQualifier; myValue = value; myContainer = container; myIsReturnedVal = isReturnedVal; + myIsIPythonHidden = isIPythonHidden; myErrorOnEval = errorOnEval; myParent = parent; myFrameAccessor = frameAccessor; @@ -78,12 +81,17 @@ public class PyDebugValue extends XNamedValue { return myIsReturnedVal; } + public boolean isIPythonHidden() { + return myIsIPythonHidden; + } + public boolean isErrorOnEval() { return myErrorOnEval; } public PyDebugValue setParent(@Nullable PyDebugValue parent) { - return new PyDebugValue(myName, myType, myTypeQualifier, myValue, myContainer, myIsReturnedVal, myErrorOnEval, parent, myFrameAccessor); + return new PyDebugValue(myName, myType, myTypeQualifier, myValue, myContainer, myIsReturnedVal, myIsIPythonHidden, myErrorOnEval, + parent, myFrameAccessor); } public PyDebugValue getParent() { @@ -237,8 +245,8 @@ public class PyDebugValue extends XNamedValue { } public PyDebugValue setName(String newName) { - PyDebugValue value = new PyDebugValue(newName, myType, myTypeQualifier, myValue, myContainer, myIsReturnedVal, myErrorOnEval, myParent, - myFrameAccessor); + PyDebugValue value = new PyDebugValue(newName, myType, myTypeQualifier, myValue, myContainer, myIsReturnedVal, myIsIPythonHidden, + myErrorOnEval, myParent, myFrameAccessor); value.setTempName(myTempName); return value; } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PyReferringObjectsValue.java b/python/pydevSrc/com/jetbrains/python/debugger/PyReferringObjectsValue.java index 0225e8fb7538..b834ad74f8c1 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/PyReferringObjectsValue.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/PyReferringObjectsValue.java @@ -31,7 +31,7 @@ public class PyReferringObjectsValue extends PyDebugValue { String typeQualifier, String value, boolean container, boolean isReturnedVal, boolean errorOnEval, @NotNull PyFrameAccessor frameAccessor) { - super(name, type, typeQualifier, value, container, isReturnedVal, errorOnEval, frameAccessor); + super(name, type, typeQualifier, value, container, isReturnedVal, false, errorOnEval, frameAccessor); myReferrersLoader = frameAccessor.getReferrersLoader(); } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetFrameCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetFrameCommand.java index 96f687b46bd0..e9ac6b810f01 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetFrameCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetFrameCommand.java @@ -48,7 +48,7 @@ public class GetFrameCommand extends AbstractFrameCommand { protected PyDebugValue extend(final PyDebugValue value) { return new PyDebugValue(value.getName(), value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), - value.isReturnedVal(), value.isErrorOnEval(), null, myDebugProcess); + value.isReturnedVal(), value.isIPythonHidden(), value.isErrorOnEval(), null, myDebugProcess); } public XValueChildrenList getVariables() { diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetVariableCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetVariableCommand.java index 0a62af8eee80..6acf73d8dd0a 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetVariableCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/GetVariableCommand.java @@ -51,7 +51,7 @@ public class GetVariableCommand extends GetFrameCommand { @Override protected PyDebugValue extend(final PyDebugValue value) { return new PyDebugValue(value.getName(), value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), - value.isReturnedVal(), value.isErrorOnEval(), myParent, + value.isReturnedVal(), value.isIPythonHidden(), value.isErrorOnEval(), myParent, myDebugProcess); } } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java index fc6635826465..f22ed618c0f9 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java @@ -267,6 +267,7 @@ public class ProtocolParser { String value = readString(reader, "value", null); final String isContainer = readString(reader, "isContainer", ""); final String isReturnedValue = readString(reader, "isRetVal", ""); + final String isIPythonHidden = readString(reader, "isIPythonHidden", ""); final String isErrorOnEval = readString(reader, "isErrorOnEval", ""); if (value.startsWith(type + ": ")) { // drop unneeded prefix @@ -274,7 +275,7 @@ public class ProtocolParser { } return new PyDebugValue(name, type, qualifier, value, "True".equals(isContainer), "True".equals(isReturnedValue), - "True".equals(isErrorOnEval), frameAccessor); + "True".equals(isIPythonHidden), "True".equals(isErrorOnEval), frameAccessor); } public static ArrayChunk parseArrayValues(final String text, final PyFrameAccessor frameAccessor) throws PyDebuggerException { @@ -293,7 +294,7 @@ public class ProtocolParser { result.setType(readString(reader, "type", null)); result.setMax(readString(reader, "max", null)); result.setMin(readString(reader, "min", null)); - result.setValue(new PyDebugValue(slice, null, null, null, false, false, false, frameAccessor)); + result.setValue(new PyDebugValue(slice, null, null, null, false, false, false, false, frameAccessor)); reader.moveUp(); } if ("headerdata".equals(reader.peekNextChild())) { diff --git a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java index ab732a6807c6..989dee3fa1a9 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java +++ b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; public class PyDebuggerEvaluator extends XDebuggerEvaluator { - private static final PyDebugValue NONE = new PyDebugValue("", "NoneType", null, "None", false, false, false, null, null); + private static final PyDebugValue NONE = new PyDebugValue("", "NoneType", null, "None", false, false, false, false, null, null); private Project myProject; private final PyFrameAccessor myDebugProcess; diff --git a/python/src/com/jetbrains/python/debugger/PyStackFrame.java b/python/src/com/jetbrains/python/debugger/PyStackFrame.java index 549ab26263bc..cfe71ec79a7b 100644 --- a/python/src/com/jetbrains/python/debugger/PyStackFrame.java +++ b/python/src/com/jetbrains/python/debugger/PyStackFrame.java @@ -147,12 +147,16 @@ public class PyStackFrame extends XStackFrame { XValueChildrenList filteredChildren = new XValueChildrenList(); final HashMap returnedValues = new HashMap<>(); final HashMap specialValues = new HashMap<>(); + final HashMap ipythonHidden = new HashMap<>(); for (int i = 0; i < children.size(); i++) { XValue value = children.getValue(i); String name = children.getName(i); if ((value instanceof PyDebugValue) && ((PyDebugValue)value).isReturnedVal()) { returnedValues.put(name, value); } + else if ((value instanceof PyDebugValue) && ((PyDebugValue)value).isIPythonHidden()) { + ipythonHidden.put(name, value); + } else if (name.startsWith(DOUBLE_UNDERSCORE) && (name.endsWith(DOUBLE_UNDERSCORE))) { specialValues.put(name, value); } @@ -160,13 +164,16 @@ public class PyStackFrame extends XStackFrame { filteredChildren.add(name, value); } } - node.addChildren(filteredChildren, returnedValues.isEmpty() && specialValues.isEmpty()); + node.addChildren(filteredChildren, returnedValues.isEmpty() && specialValues.isEmpty() && ipythonHidden.isEmpty()); if (!returnedValues.isEmpty()) { addReturnedValuesGroup(node, returnedValues); } if (!specialValues.isEmpty()) { addSpecialValuesGroup(node, specialValues); } + if (!ipythonHidden.isEmpty()) { + addIPythonVariablesGroup(node, ipythonHidden); + } } private static void addReturnedValuesGroup(@NotNull final XCompositeNode node, Map returnedValues) { @@ -211,6 +218,27 @@ public class PyStackFrame extends XStackFrame { node.addChildren(XValueChildrenList.topGroups(group), true); } + private static void addIPythonVariablesGroup(@NotNull final XCompositeNode node, Map specialValues) { + final ArrayList group = Lists.newArrayList(); + group.add(new XValueGroup("IPython Variables") { + @Override + public void computeChildren(@NotNull XCompositeNode node) { + XValueChildrenList list = new XValueChildrenList(); + for (Map.Entry entry : specialValues.entrySet()) { + list.add(entry.getKey(), entry.getValue()); + } + node.addChildren(list, true); + } + + @Nullable + @Override + public Icon getIcon() { + return PythonIcons.Python.Debug.SpecialVar; + } + }); + node.addChildren(XValueChildrenList.topGroups(group), true); + } + public String getThreadId() { return myFrameInfo.getThreadId(); } diff --git a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java index 263b69daf670..8fd33a7035cc 100644 --- a/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java +++ b/python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java @@ -204,7 +204,7 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource PyDebugValue parent = value.getParent(); final PyDebugValue slicedValue = new PyDebugValue(slice, value.getType(), null, value.getValue(), value.isContainer(), value.isReturnedVal(), value.isErrorOnEval(), - parent, value.getFrameAccessor()); + value.isIPythonHidden(), parent, value.getFrameAccessor()); final String format = getFormat().isEmpty() ? "%" : getFormat(); @@ -227,8 +227,8 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource public ArrayChunk getChunk(int rowOffset, int colOffset, int rows, int cols) throws PyDebuggerException { final PyDebugValue slicedValue = new PyDebugValue(getSliceText(), myValue.getType(), myValue.getTypeQualifier(), myValue.getValue(), myValue.isContainer(), - myValue.isErrorOnEval(), myValue.isReturnedVal(), - myValue.getParent(), myValue.getFrameAccessor()); + myValue.isErrorOnEval(), myValue.isReturnedVal(), myValue.isIPythonHidden(), myValue.getParent(), + myValue.getFrameAccessor()); final String format = getFormat().isEmpty() ? "%" : getFormat(); return myValue.getFrameAccessor().getArrayItems(slicedValue, rowOffset, colOffset, rows, cols, format);