PY-57014 (WIP): Use `Path instead of String for suggestLocalHomePath`

GitOrigin-RevId: af1a29aa02a943a5b2a952363ac9d9e53c56a6bc
This commit is contained in:
Ilya.Kazakevich
2022-10-26 21:46:46 +02:00
committed by intellij-monorepo-bot
parent 8d83b86e8b
commit 96c3efd4c8
9 changed files with 55 additions and 32 deletions

View File

@@ -16,6 +16,7 @@ import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PatternUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.run.CommandLinePatcher;
import com.jetbrains.python.sdk.PyRemoteSdkAdditionalDataMarker;
@@ -77,7 +78,14 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
/**
* On local targets some flavours could be detected. It returns path to python interpreters for such cases.
*/
@NotNull
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable final Module module, @Nullable final UserDataHolder context) {
return ContainerUtil.map(suggestHomePaths(module, context), Path::of);
}
/**
* @deprecated use {@link #suggestLocalHomePaths(Module, UserDataHolder)}
*/
@Deprecated
public Collection<String> suggestHomePaths(@Nullable final Module module, @Nullable final UserDataHolder context) {
return Collections.emptyList();
}

View File

@@ -51,7 +51,9 @@ import com.jetbrains.python.packaging.ui.PyPackageManagementService
import com.jetbrains.python.psi.LanguageLevel
import com.jetbrains.python.remote.PyRemoteSdkAdditionalData
import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase
import com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory
import com.jetbrains.python.sdk.add.target.PyDetectedSdkAdditionalData
import com.jetbrains.python.sdk.add.target.createDetectedSdk
import com.jetbrains.python.sdk.flavors.PyFlavorAndData
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor
@@ -64,6 +66,11 @@ import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.div
import kotlin.io.path.name
import kotlin.io.path.pathString
private data class TargetAndPath(val target: TargetEnvironmentConfiguration?,
val path: FullPathOnTarget?)
/**
* @author vlan
@@ -96,14 +103,17 @@ fun filterSystemWideSdks(existingSdks: List<Sdk>): List<Sdk> {
}
@JvmOverloads
fun detectSystemWideSdks(module: Module?, existingSdks: List<Sdk>, context: UserDataHolder = UserDataHolderBase()): List<PyDetectedSdk> {
fun detectSystemWideSdks(module: Module?,
existingSdks: List<Sdk>,
context: UserDataHolder = UserDataHolderBase()): List<PyDetectedSdk> {
if (module != null && module.isDisposed) return emptyList()
val existingPaths = existingSdks.map { it.homePath }.toSet()
val target = module?.let { PythonInterpreterTargetEnvironmentFactory.guessTargetConfigurationByModule(it) }
val existingPaths = existingSdks.mapTo(HashSet()) { TargetAndPath(it.targetEnvConfiguration, it.homePath) }
return PythonSdkFlavor.getApplicableFlavors(false)
.asSequence()
.flatMap { it.suggestHomePaths(module, context).asSequence() }
.filter { it !in existingPaths }
.map { PyDetectedSdk(it) }
.flatMap { it.suggestLocalHomePaths(module, context).asSequence() }
.filter { TargetAndPath(target, it.pathString) !in existingPaths }
.map { createDetectedSdk(it.name, target) }
.sortedWith(compareBy<PyDetectedSdk>({ it.guessedLanguageLevel },
{ it.homePath }).reversed())
.toList()
@@ -114,7 +124,7 @@ fun resetSystemWideSdksDetectors() {
}
fun detectVirtualEnvs(module: Module?, existingSdks: List<Sdk>, context: UserDataHolder): List<PyDetectedSdk> =
filterSuggestedPaths(VirtualEnvSdkFlavor.getInstance().suggestHomePaths(module, context), existingSdks, module, context)
filterSuggestedPaths(VirtualEnvSdkFlavor.getInstance().suggestLocalHomePaths(module, context), existingSdks, module, context)
fun filterSharedCondaEnvs(module: Module?, existingSdks: List<Sdk>): List<Sdk> {
return existingSdks.filter { it.sdkType is PythonSdkType && PythonSdkUtil.isConda(it) && !it.isAssociatedWithAnotherModule(module) }
@@ -122,7 +132,7 @@ fun filterSharedCondaEnvs(module: Module?, existingSdks: List<Sdk>): List<Sdk> {
fun detectCondaEnvs(module: Module?, existingSdks: List<Sdk>, context: UserDataHolder): List<PyDetectedSdk> =
filterSuggestedPaths(
CondaEnvSdkFlavor.getInstance().suggestHomePaths(module, context), existingSdks, module, context, true)
CondaEnvSdkFlavor.getInstance().suggestLocalHomePaths(module, context), existingSdks, module, context, true)
fun filterAssociatedSdks(module: Module, existingSdks: List<Sdk>): List<Sdk> {
return existingSdks.filter { it.sdkType is PythonSdkType && it.isAssociatedWithModule(module) }
@@ -382,18 +392,20 @@ fun Sdk.getOrCreateAdditionalData(): PythonSdkAdditionalData {
return newData
}
private fun filterSuggestedPaths(suggestedPaths: Collection<String>,
private fun filterSuggestedPaths(suggestedPaths: Collection<Path>,
existingSdks: List<Sdk>,
module: Module?,
context: UserDataHolder,
mayContainCondaEnvs: Boolean = false): List<PyDetectedSdk> {
val existingPaths = existingSdks.mapTo(HashSet()) { it.homePath }
val target = module?.let { PythonInterpreterTargetEnvironmentFactory.guessTargetConfigurationByModule(it) }
val existingPaths = existingSdks.mapTo(HashSet()) { TargetAndPath(it.targetEnvConfiguration, it.homePath) }
val baseDirFromContext = context.getUserData(BASE_DIR)
return suggestedPaths
.asSequence()
.filterNot { it in existingPaths }
.filterNot { TargetAndPath(target, it.toString()) in existingPaths }
.distinct()
.map { PyDetectedSdk(it) }
.map { createDetectedSdk(it.toString(), target) }
.sortedWith(
compareBy(
{ !it.isAssociatedWithModule(module) && !it.isLocatedInsideBaseDir(baseDirFromContext) },

View File

@@ -6,6 +6,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PatternUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.sdk.PythonEnvUtil;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
@@ -13,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.nio.file.Path;
import java.util.*;
import java.util.regex.Pattern;
@@ -38,9 +40,8 @@ public final class IronPythonSdkFlavor extends PythonSdkFlavor<PyFlavorData.Empt
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
Set<String> result = new TreeSet<>();
String root = System.getenv("ProgramFiles(x86)");
if (root == null) {
@@ -61,7 +62,7 @@ public final class IronPythonSdkFlavor extends PythonSdkFlavor<PyFlavorData.Empt
}
WinPythonSdkFlavor.findInPath(result, "ipy.exe");
WinPythonSdkFlavor.findInPath(result, "ipy64.exe");
return result;
return ContainerUtil.map(result, Path::of);
}
@Override

View File

@@ -16,11 +16,13 @@ import com.intellij.openapi.util.text.HtmlChunk;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.sdk.PyDetectedSdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -46,9 +48,8 @@ public final class MacPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empt
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
Set<String> candidates = new HashSet<>();
collectPythonInstallations("/Library/Frameworks/Python.framework/Versions", candidates);
collectPythonInstallations("/System/Library/Frameworks/Python.framework/Versions", candidates);
@@ -57,7 +58,7 @@ public final class MacPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empt
if (areCommandLineDeveloperToolsAvailable()) {
UnixPythonSdkFlavor.collectUnixPythons("/usr/bin", candidates);
}
return candidates;
return ContainerUtil.map(candidates, Path::of);
}
private static void collectPythonInstallations(String pythonPath, Set<String> candidates) {

View File

@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
@@ -34,9 +35,8 @@ public final class PyRemoteSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
return new ArrayList<>();
}

View File

@@ -9,13 +9,16 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public final class UnixPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
@@ -40,10 +43,9 @@ public final class UnixPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
return getDefaultUnixPythons(null);
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
return ContainerUtil.map(getDefaultUnixPythons(null), Path::of);
}
@NotNull

View File

@@ -49,10 +49,9 @@ public final class VirtualEnvSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
return ReadAction.compute(() -> {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
return ContainerUtil.map(ReadAction.compute(() -> {
final List<String> candidates = new ArrayList<>();
final VirtualFile baseDirFromModule = module == null ? null : BasePySdkExtKt.getBaseDir(module);
final Path baseDirFromContext = context == null ? null : context.getUserData(PySdkExtKt.getBASE_DIR());
@@ -78,7 +77,7 @@ public final class VirtualEnvSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
}
return ContainerUtil.filter(candidates, PythonSdkUtil::isVirtualEnv);
});
}), Path::of);
}
@Nullable

View File

@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import static com.jetbrains.python.sdk.flavors.WinAppxToolsKt.getAppxFiles;
import static com.jetbrains.python.sdk.flavors.WinAppxToolsKt.getAppxProduct;
@@ -69,13 +70,12 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
return PyFlavorData.Empty.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable final Module module, @Nullable final UserDataHolder context) {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable final Module module, @Nullable final UserDataHolder context) {
Set<String> candidates = new TreeSet<>();
findInCandidatePaths(candidates, "python.exe", "jython.bat", "pypy.exe");
findInstallations(candidates, "python.exe", PythonHelpersLocator.getHelpersRoot().getParent());
return candidates;
return ContainerUtil.map(candidates, Path::of);
}
private void findInCandidatePaths(Set<String> candidates, String... exe_names) {

View File

@@ -21,6 +21,7 @@ import org.jetbrains.annotations.SystemDependent;
import javax.swing.*;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
@@ -58,9 +59,8 @@ public final class CondaEnvSdkFlavor extends CPythonSdkFlavor<PyCondaFlavorData>
return PyCondaFlavorData.class;
}
@NotNull
@Override
public Collection<String> suggestHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
public @NotNull Collection<@NotNull Path> suggestLocalHomePaths(@Nullable Module module, @Nullable UserDataHolder context) {
// There is no such thing as "conda homepath" since conda doesn't store python path
return Collections.emptyList();
}