mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
PY-80388: Exclude conda from system pythons.
What happened: `WinPythonSdkFlavor` returned all pythons from the `Path` environment variable. Conda might be installed there. How did we fix it: all flavors now report paths using protected functions. The parent class then filters results to drop pythons with incorrect flavor. See `com.jetbrains.python.sdk.flavors.PythonSdkFlavor.suggestLocalHomePaths`. GitOrigin-RevId: 7f2ef52a427ac07a625305c8371d985e2a7e0575
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9dd749c19b
commit
2d1ff1fec7
@@ -17,7 +17,6 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PatternUtil;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.psi.icons.PythonPsiApiIcons;
|
||||
import com.jetbrains.python.run.CommandLinePatcher;
|
||||
@@ -33,10 +32,11 @@ import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.jetbrains.python.venvReader.ResolveUtilKt.tryResolvePath;
|
||||
import static com.jetbrains.python.sdk.flavors.PySdkFlavorUtilKt.getFileExecutionError;
|
||||
import static com.jetbrains.python.sdk.flavors.PySdkFlavorUtilKt.getFileExecutionErrorOnEdt;
|
||||
import static com.jetbrains.python.venvReader.ResolveUtilKt.tryResolvePath;
|
||||
|
||||
|
||||
/**
|
||||
@@ -97,21 +97,31 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
}
|
||||
|
||||
/**
|
||||
* On local targets some flavours could be detected. It returns path to python interpreters for such cases.
|
||||
* Flavors that are aware of some system pythons must return them there.
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(final @Nullable Module module, final @Nullable UserDataHolder context) {
|
||||
return ContainerUtil.map(suggestHomePaths(module, context), Path::of);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #suggestLocalHomePaths(Module, UserDataHolder)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public Collection<String> suggestHomePaths(final @Nullable Module module, final @Nullable UserDataHolder context) {
|
||||
protected @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(final @Nullable Module module,
|
||||
final @Nullable UserDataHolder context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* On local targets some flavors could be detected. It returns a path to python interpreters for such cases.
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
public final @NotNull Collection<@NotNull Path> suggestLocalHomePaths(final @Nullable Module module,
|
||||
final @Nullable UserDataHolder context) {
|
||||
return suggestLocalHomePathsImpl(module, context).stream().filter(path -> {
|
||||
var flavor = tryDetectFlavorByLocalPath(path.toString());
|
||||
boolean correctFlavor = flavor != null && flavor.getClass().equals(getClass());
|
||||
// Some flavors might report foreign pythons: i.e Windows might find conda on PATH.
|
||||
if (!correctFlavor) {
|
||||
LOG.info(String.format("Path %s has a wrong flavor, not %s, skipping", path, this));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).collect(Collectors.toSet()).stream().sorted().toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flavor is added to result in {@link #getApplicableFlavors()} if this method returns true.
|
||||
@@ -275,7 +285,7 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects {@link PythonSdkFlavor} for local python path
|
||||
* Detects {@link PythonSdkFlavor} for a local python path
|
||||
*/
|
||||
@RequiresBackgroundThread(generateAssertion = false) //No warning yet as there are usages: to be fixed
|
||||
public static @Nullable PythonSdkFlavor<?> tryDetectFlavorByLocalPath(@NotNull String sdkPath) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.text.HtmlBuilder;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.sdk.PyDetectedSdk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -45,8 +46,9 @@ public final class MacPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empt
|
||||
return PyFlavorData.Empty.class;
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
protected @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
Set<Path> candidates = new HashSet<>();
|
||||
collectPythonInstallations(Path.of("/Library/Frameworks/Python.framework/Versions"), candidates);
|
||||
collectPythonInstallations(Path.of("/System/Library/Frameworks/Python.framework/Versions"), candidates);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.venvReader.VirtualEnvReader;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -42,8 +43,9 @@ public final class UnixPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
|
||||
return PyFlavorData.Empty.class;
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
protected @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
return getDefaultUnixPythons();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.icons.PythonIcons;
|
||||
import com.jetbrains.python.sdk.BasePySdkExtKt;
|
||||
@@ -42,8 +43,9 @@ public final class VirtualEnvSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
|
||||
return PyFlavorData.Empty.class;
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
protected @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
return ReadAction.compute(() -> {
|
||||
final var candidates = new ArrayList<Path>();
|
||||
|
||||
@@ -69,10 +71,6 @@ public final class VirtualEnvSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
|
||||
});
|
||||
}
|
||||
|
||||
public static @NotNull Path getDefaultLocation() {
|
||||
return VirtualEnvReader.getInstance().getVEnvRootDir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
if (!super.isValidSdkPath(pathStr)) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
|
||||
import com.intellij.execution.target.TargetEnvironmentConfiguration;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -11,6 +12,7 @@ import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.concurrency.SynchronizedClearableLazy;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -84,7 +86,8 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
|
||||
|
||||
@RequiresBackgroundThread
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(final @Nullable Module module, final @Nullable UserDataHolder context) {
|
||||
protected final @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(final @Nullable Module module,
|
||||
final @Nullable UserDataHolder context) {
|
||||
Set<String> candidates = new TreeSet<>();
|
||||
findInCandidatePaths(candidates, "python.exe", "pypy.exe");
|
||||
findInstallations(candidates, "python.exe", PythonHelpersLocator.getCommunityHelpersRoot().getParent().toString());
|
||||
@@ -127,6 +130,7 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
|
||||
return path != null && isPythonFromStore(path); // Python from store might be non-executable, but still usable
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
private boolean isPythonFromStore(@NotNull Path path) {
|
||||
String pathStr = path.toString();
|
||||
if (myAppxCache.getValue().contains(pathStr)) {
|
||||
@@ -161,8 +165,9 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
|
||||
}
|
||||
}
|
||||
|
||||
public static void findInPath(Collection<? super String> candidates, String exeName) {
|
||||
final String path = System.getenv("PATH");
|
||||
@RequiresBackgroundThread
|
||||
private static void findInPath(@NotNull Collection<? super @NotNull String> candidates, @NotNull String exeName) {
|
||||
final String path = PathEnvironmentVariableUtil.getPathVariableValue(); //can be Path or PATH
|
||||
if (path == null) return;
|
||||
for (String pathEntry : StringUtil.split(path, ";")) {
|
||||
if (pathEntry.startsWith("\"") && pathEntry.endsWith("\"")) {
|
||||
|
||||
@@ -58,8 +58,9 @@ public final class CondaEnvSdkFlavor extends CPythonSdkFlavor<PyCondaFlavorData>
|
||||
return PyCondaFlavorData.class;
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
protected @NotNull Collection<@NotNull Path> suggestLocalHomePathsImpl(@Nullable Module module, @Nullable UserDataHolder context) {
|
||||
// There is no such thing as "conda homepath" since conda doesn't store python path
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user