DS-5113 Removed additional calls in PyConsoleRuntimeEnvService

GitOrigin-RevId: 770f9ae0696b67ba1603e18a6310b3ca15f626a9
This commit is contained in:
Olga.Lavrichenko
2023-06-11 18:14:40 +00:00
committed by intellij-monorepo-bot
parent 09003c4c66
commit 1761aebe4a
4 changed files with 140 additions and 124 deletions

View File

@@ -29,7 +29,7 @@ import java.util.regex.Pattern;
import static com.jetbrains.python.debugger.PyDebugValueGroupsKt.*;
public class PyDebugValue extends XNamedValue {
private static final Logger LOG = Logger.getInstance(PyDebugValue.class);
protected static final Logger LOG = Logger.getInstance(PyDebugValue.class);
private static final String DATA_FRAME = "DataFrame";
private static final String SERIES = "Series";
private static final Map<String, String> EVALUATOR_POSTFIXES = ImmutableMap.of(
@@ -38,7 +38,7 @@ public class PyDebugValue extends XNamedValue {
SERIES, SERIES,
"GeoDataFrame", DATA_FRAME,
"GeoSeries", SERIES
);
);
private static final int MAX_ITEMS_TO_HANDLE = 100;
public static final int MAX_VALUE = 256;
public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
@@ -48,16 +48,16 @@ public class PyDebugValue extends XNamedValue {
private @Nullable String myTempName = null;
private final @Nullable String myType;
private final @Nullable String myTypeQualifier;
private @Nullable String myValue;
protected @Nullable String myValue;
private final boolean myContainer;
private final @Nullable String myShape;
private final boolean myIsReturnedVal;
private final boolean myIsIPythonHidden;
private @Nullable PyDebugValue myParent;
private @Nullable String myId = null;
private ValuesPolicy myLoadValuePolicy;
protected ValuesPolicy myLoadValuePolicy;
private @NotNull PyFrameAccessor myFrameAccessor;
private @NotNull final List<XValueNode> myValueNodes = new ArrayList<>();
protected @NotNull final List<XValueNode> myValueNodes = new ArrayList<>();
private final boolean myErrorOnEval;
private final @Nullable String myTypeRendererId;
private int myOffset;
@@ -87,7 +87,8 @@ public class PyDebugValue extends XNamedValue {
boolean errorOnEval,
@Nullable String typeRendererId,
@NotNull final PyFrameAccessor frameAccessor) {
this(name, type, typeQualifier, value, container, shape, isReturnedVal, isIPythonHidden, errorOnEval, typeRendererId, null, frameAccessor);
this(name, type, typeQualifier, value, container, shape, isReturnedVal, isIPythonHidden, errorOnEval, typeRendererId, null,
frameAccessor);
}
/**
@@ -438,7 +439,9 @@ public class PyDebugValue extends XNamedValue {
return variables;
}
public static void getAsyncValues(@Nullable XStackFrame frame, @NotNull PyFrameAccessor frameAccessor, @NotNull XValueChildrenList childrenList) {
public static void getAsyncValues(@Nullable XStackFrame frame,
@NotNull PyFrameAccessor frameAccessor,
@NotNull XValueChildrenList childrenList) {
List<PyFrameAccessor.PyAsyncValue<String>> variables = getAsyncValuesFromChildren(childrenList);
int chunkSize = Math.max(1, variables.size() / AVAILABLE_PROCESSORS);
int left = 0;
@@ -497,7 +500,8 @@ public class PyDebugValue extends XNamedValue {
values = processLargeCollection(values);
}
if (myFrameAccessor.isSimplifiedView()) {
extractChildrenToGroup(PydevBundle.message("pydev.value.protected.attributes.group.name"), AllIcons.Nodes.C_protected, node, values, (String name) -> name.startsWith("_"),
extractChildrenToGroup(PydevBundle.message("pydev.value.protected.attributes.group.name"), AllIcons.Nodes.C_protected, node,
values, (String name) -> name.startsWith("_"),
getPROTECTED_ATTRS_EXCLUDED());
}
else {
@@ -547,7 +551,8 @@ public class PyDebugValue extends XNamedValue {
return new PyReferringObjectsValue(PyDebugValue.this);
}
};
} else {
}
else {
return null;
}
}
@@ -591,7 +596,7 @@ public class PyDebugValue extends XNamedValue {
return true;
}
private static final Pattern IS_TYPE_DECLARATION = Pattern.compile("<(?:class|type)\\s*'(?<TYPE>.*?)'>");
private static final Pattern IS_TYPE_DECLARATION = Pattern.compile("<(?:class|type)\\s*'(?<TYPE>.*?)'>");
@Override
public void computeTypeSourcePosition(@NotNull XNavigatable navigatable) {
@@ -613,8 +618,9 @@ public class PyDebugValue extends XNamedValue {
@Nullable
public String getQualifiedType() {
if (Strings.isNullOrEmpty(myType))
if (Strings.isNullOrEmpty(myType)) {
return null;
}
return (myTypeQualifier == null) ? myType : (myTypeQualifier + "." + myType);
}
@@ -648,9 +654,11 @@ public class PyDebugValue extends XNamedValue {
if (values.size() > 0 && isLen(values.getName(lastIndex))) {
PyDebugValue len = (PyDebugValue)values.getValue(lastIndex);
try {
if (myCollectionLength == -1 && len.getValue() != null)
if (myCollectionLength == -1 && len.getValue() != null) {
myCollectionLength = Integer.parseInt(len.getValue());
} catch (NumberFormatException ex) {
}
}
catch (NumberFormatException ex) {
// Do nothing.
}
}
@@ -660,7 +668,7 @@ public class PyDebugValue extends XNamedValue {
if (values.size() > 0 && isLargeCollection()) {
if (myOffset + Math.min(MAX_ITEMS_TO_HANDLE, values.size()) < myCollectionLength) {
XValueChildrenList newValues = new XValueChildrenList();
for(int i = 0; i < values.size() - 1; i++) {
for (int i = 0; i < values.size() - 1; i++) {
newValues.add(values.getName(i), values.getValue(i));
}
return newValues;

View File

@@ -2,33 +2,22 @@
package com.jetbrains.python.debugger.values;
import com.intellij.util.SmartFMap;
import com.intellij.xdebugger.frame.XValueNode;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.debugger.PyFrameAccessor;
import com.jetbrains.python.debugger.pydev.PyDebugCallback;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
import static com.jetbrains.python.debugger.values.DataFrameDebugValueUtilKt.getColumnData;
public final class DataFrameDebugValue extends PyDebugValue {
private final ColumnNode treeColumns = new ColumnNode();
private static final String PANDAS_COLUMN_NAMES_CODE = """
try:
import json
if str(%1$s.columns.__class__) == "<class 'pandas.core.indexes.multi.MultiIndex'>":
print(json.dumps({"columns": list(%1$s.columns), "isMultiIndex": True}))
else:
print(json.dumps({"columns": [[_] for _ in list(%1$s.columns)], "isMultiIndex": False}))
except:
pass
""";
private static final String PANDAS_COLUMN_NAMES_CODE_ONE_LINE =
"__import__('json').dumps({\"columns\": list(%1$s.columns), \"isMultiIndex\": True}) " +
"if str(%1$s.columns.__class__) == \"<class 'pandas.core.indexes.multi.MultiIndex'>\" " +
"else __import__('json').dumps({\"columns\": [[_] for _ in list(%1$s.columns)], \"isMultiIndex\": False})";
public DataFrameDebugValue(@NotNull String name,
@Nullable String type,
@Nullable String typeQualifier,
@@ -67,6 +56,34 @@ public final class DataFrameDebugValue extends PyDebugValue {
super(value);
}
@Override
@NotNull
public PyDebugCallback<String> createDebugValueCallback() {
return new PyDebugCallback<>() {
@Override
public void ok(String value) {
myLoadValuePolicy = ValuesPolicy.SYNC;
myValue = value;
DataFrameDebugValue.InformationColumns columns = getColumnData(value);
if (columns != null) {
setColumns(columns);
}
for (XValueNode node : myValueNodes) {
if (node != null && !node.isObsolete()) {
updateNodeValueAfterLoading(node, value, "", null);
}
}
}
@Override
public void error(PyDebuggerException exception) {
LOG.error(exception.getMessage());
}
};
}
public ColumnNode getTreeColumns() {
return treeColumns;
}
@@ -83,22 +100,6 @@ public final class DataFrameDebugValue extends PyDebugValue {
}
}
private static final String PYDEV_COMMAND_PREFIX = "# pydev_util_command\n";
/**
* @param dfName - DataFrame identifier (it must be a valid Python identifier, either will be a useless function call)
* @param oneLine - flag to construct one/multi line Python script
*/
public static String commandExtractPandasColumns(@NotNull String dfName, boolean oneLine) {
if (oneLine) {
return String.format(PANDAS_COLUMN_NAMES_CODE_ONE_LINE, dfName);
}
else {
return PYDEV_COMMAND_PREFIX +
String.format(PANDAS_COLUMN_NAMES_CODE, dfName);
}
}
public static final class InformationColumns {
public boolean isMultiIndex;
public List<List<String>> columns;

View File

@@ -1,10 +1,15 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.debugger.values
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.NlsSafe
import com.jetbrains.python.debugger.PyDebugValue
import org.jetbrains.annotations.ApiStatus
import java.lang.invoke.MethodHandles
/**
*
* This function extracts children-columns of current sub-table.
* This function extracts children-columns of the current sub-table.
* @param treeColumns - DataFrame columns in a tree structure
* @param columnsBefore - list of columns-nodes (path to the current node)
* @return set of children of an exact node
@@ -25,4 +30,74 @@ fun completePandasDataFrameColumns(treeColumns: DataFrameDebugValue.ColumnNode,
else {
treeColumns.childrenName
}
}
}
private val LOG = Logger.getInstance(MethodHandles.lookup().lookupClass())
private val MULTI_INDEX_DATA_REGEX = Regex("\\[(\\(.*?(?=\\)).*?)+]")
private val MULTI_INDEX_COLUMN_GROUP_REGEX = Regex("\\((.*?(?=\\).*?))\\)")
private val COLUMN_NAMES_REGEX = Regex("'(.*?(?<!\\\\))'|\"(.*?(?<!\\\\))\"")
/**
* Retrieves column names and index data from [PyDebugValue.getValue].
*
* The [value] is produced by _get_df_variable_repr.
*/
@ApiStatus.Internal
fun getColumnData(value: @NlsSafe String): DataFrameDebugValue.InformationColumns? {
val columnData = getData(value) ?: run {
LOG.warn("Can't retrieve column data from ${value}")
return null
}
getMultiIndexData(columnData)?.let { return it }
val columns = COLUMN_NAMES_REGEX.findAll(columnData).map { listOf(it.groups.filterNotNull().last().value) }.toList()
return if (columns.isNotEmpty()) {
DataFrameDebugValue.InformationColumns().apply {
this.isMultiIndex = false
this.columns = columns
}
}
else {
null
}
}
private fun getData(value: String): String? {
var escaped = false
var inSingleQuotes = false
var inDoubleQuotes = false
val index = value.indexOfFirst { char ->
inSingleQuotes = inSingleQuotes.xor(char == '\'' && !escaped) && !inDoubleQuotes
inDoubleQuotes = inDoubleQuotes.xor(char == '"' && !escaped) && !inSingleQuotes
escaped = !escaped && char == '\\'
!inSingleQuotes && !inDoubleQuotes && char == ']'
}
return if (index != -1) {
value.substring(0, index + 1)
}
else {
null
}
}
private fun getMultiIndexData(columnData: @NlsSafe String): DataFrameDebugValue.InformationColumns? {
MULTI_INDEX_DATA_REGEX.find(columnData)?.groups?.get(0)?.value ?: return null
val columns = MULTI_INDEX_COLUMN_GROUP_REGEX.findAll(columnData).map { result ->
COLUMN_NAMES_REGEX.findAll(result.value).map { it.groups.filterNotNull().last().value }.toList()
}.toList()
return if (columns.isNotEmpty()) {
DataFrameDebugValue.InformationColumns().apply {
this.isMultiIndex = true
this.columns = columns
}
}
else {
null
}
}