mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-31048 Restore auto-detection of virtualenvs inside projects upon opening them for the first time
We used to detect them using an ad-hoc solution in the `PythonSdkConfigurator`. Since we switched to re-using `detectVirtualEnvs()` which is based on `PythonSdkFlavor.suggestHomePaths()`, the detection stopped working. The reason was the we didn't have the project in the default data context during its creation and it was needed as a starting point for searching for virtualenvs. We now pass an explicit module for it.
This commit is contained in:
@@ -39,8 +39,8 @@ class PythonSdkConfigurator : DirectoryProjectConfigurator {
|
||||
private fun findExistingSystemWideSdk(existingSdks: List<Sdk>) =
|
||||
existingSdks.filter { it.isSystemWide }.sortedWith(PreferredSdkComparator.INSTANCE).firstOrNull()
|
||||
|
||||
private fun findDetectedSystemWideSdk(existingSdks: List<Sdk>) =
|
||||
detectSystemWideSdks(existingSdks).firstOrNull()
|
||||
private fun findDetectedSystemWideSdk(module: Module?, existingSdks: List<Sdk>) =
|
||||
detectSystemWideSdks(module, existingSdks).firstOrNull()
|
||||
}
|
||||
|
||||
override fun configureProject(project: Project?, baseDir: VirtualFile, moduleRef: Ref<Module>?) {
|
||||
@@ -75,7 +75,7 @@ class PythonSdkConfigurator : DirectoryProjectConfigurator {
|
||||
return
|
||||
}
|
||||
|
||||
findDetectedSystemWideSdk(existingSdks)?.let {
|
||||
findDetectedSystemWideSdk(module, existingSdks)?.let {
|
||||
SdkConfigurationUtil.createAndAddSDK(it.homePath, PythonSdkType.getInstance())?.apply {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, this)
|
||||
}
|
||||
|
||||
@@ -47,17 +47,17 @@ import java.nio.file.Paths
|
||||
* @author vlan
|
||||
*/
|
||||
|
||||
fun findBaseSdks(existingSdks: List<Sdk>): List<Sdk> {
|
||||
fun findBaseSdks(existingSdks: List<Sdk>, module: Module?): List<Sdk> {
|
||||
val existing = existingSdks.filter { it.sdkType is PythonSdkType && it.isSystemWide }
|
||||
val detected = detectSystemWideSdks(existingSdks)
|
||||
val detected = detectSystemWideSdks(module, existingSdks)
|
||||
return existing + detected
|
||||
}
|
||||
|
||||
fun detectSystemWideSdks(existingSdks: List<Sdk>): List<PyDetectedSdk> {
|
||||
fun detectSystemWideSdks(module: Module?, existingSdks: List<Sdk>): List<PyDetectedSdk> {
|
||||
val existingPaths = existingSdks.map { it.homePath }.toSet()
|
||||
return PythonSdkFlavor.getApplicableFlavors(false)
|
||||
.asSequence()
|
||||
.flatMap { it.suggestHomePaths().asSequence() }
|
||||
.flatMap { it.suggestHomePaths(module).asSequence() }
|
||||
.filter { it !in existingPaths }
|
||||
.map { PyDetectedSdk(it) }
|
||||
.sortedWith(compareBy<PyDetectedSdk>({ it.guessedLanguageLevel },
|
||||
@@ -66,10 +66,10 @@ fun detectSystemWideSdks(existingSdks: List<Sdk>): List<PyDetectedSdk> {
|
||||
}
|
||||
|
||||
fun detectVirtualEnvs(module: Module?, existingSdks: List<Sdk>): List<PyDetectedSdk> =
|
||||
filterSuggestedPaths(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths(), existingSdks, module)
|
||||
filterSuggestedPaths(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths(module), existingSdks, module)
|
||||
|
||||
fun detectCondaEnvs(module: Module?, existingSdks: List<Sdk>): List<PyDetectedSdk> =
|
||||
filterSuggestedPaths(CondaEnvSdkFlavor.INSTANCE.suggestHomePaths(), existingSdks, module)
|
||||
filterSuggestedPaths(CondaEnvSdkFlavor.INSTANCE.suggestHomePaths(module), existingSdks, module)
|
||||
|
||||
fun createSdkByGenerateTask(generateSdkHomePath: Task.WithResult<String, ExecutionException>,
|
||||
existingSdks: List<Sdk>,
|
||||
|
||||
@@ -147,7 +147,7 @@ public final class PythonSdkType extends SdkType {
|
||||
@Nullable
|
||||
public String suggestHomePath() {
|
||||
final Sdk[] existingSdks = ProjectJdkTable.getInstance().getAllJdks();
|
||||
final List<PyDetectedSdk> sdks = PySdkExtKt.detectSystemWideSdks(Arrays.asList(existingSdks));
|
||||
final List<PyDetectedSdk> sdks = PySdkExtKt.detectSystemWideSdks(null, Arrays.asList(existingSdks));
|
||||
final PyDetectedSdk latest = StreamEx.of(sdks).findFirst().orElse(null);
|
||||
if (latest != null) {
|
||||
return latest.getHomePath();
|
||||
|
||||
@@ -62,7 +62,7 @@ class PyAddNewVirtualEnvPanel(private val project: Project?,
|
||||
|
||||
override val panelName: String = "New environment"
|
||||
override val icon: Icon = PythonIcons.Python.Virtualenv
|
||||
private val baseSdkField = PySdkPathChoosingComboBox(findBaseSdks(existingSdks), null).apply {
|
||||
private val baseSdkField = PySdkPathChoosingComboBox(findBaseSdks(existingSdks, module), null).apply {
|
||||
val preferredSdkPath = PySdkSettings.instance.preferredVirtualEnvBaseSdk
|
||||
val detectedPreferredSdk = items.find { it.homePath == preferredSdkPath }
|
||||
selectedSdk = when {
|
||||
|
||||
@@ -76,7 +76,7 @@ class PyAddSdkDialog private constructor(private val project: Project?,
|
||||
.sortedWith(PreferredSdkComparator())
|
||||
val panels = arrayListOf<PyAddSdkView>(createVirtualEnvPanel(project, module, sdks, newProjectPath),
|
||||
createAnacondaPanel(project, module),
|
||||
PyAddSystemWideInterpreterPanel(existingSdks))
|
||||
PyAddSystemWideInterpreterPanel(module, existingSdks))
|
||||
val extendedPanels = PyAddSdkProvider.EP_NAME.extensions
|
||||
.mapNotNull {
|
||||
it.createView(project = project, module = module, newProjectPath = newProjectPath, existingSdks = existingSdks)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk.add
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.ui.ValidationInfo
|
||||
import com.intellij.ui.components.JBLabel
|
||||
@@ -28,9 +29,9 @@ import java.awt.BorderLayout
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
class PyAddSystemWideInterpreterPanel(private val existingSdks: List<Sdk>) : PyAddSdkPanel() {
|
||||
class PyAddSystemWideInterpreterPanel(module: Module?, private val existingSdks: List<Sdk>) : PyAddSdkPanel() {
|
||||
override val panelName: String = "System interpreter"
|
||||
private val sdkComboBox = PySdkPathChoosingComboBox(detectSystemWideSdks(existingSdks), null)
|
||||
private val sdkComboBox = PySdkPathChoosingComboBox(detectSystemWideSdks(module, existingSdks), null)
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
@@ -45,7 +46,7 @@ public class CondaEnvSdkFlavor extends CPythonSdkFlavor {
|
||||
public static CondaEnvSdkFlavor INSTANCE = new CondaEnvSdkFlavor();
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
List<String> candidates = new ArrayList<>();
|
||||
|
||||
for (VirtualFile file : getCondaDefaultLocations()) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PatternUtil;
|
||||
import icons.PythonIcons;
|
||||
@@ -39,7 +40,7 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
|
||||
public static IronPythonSdkFlavor INSTANCE = new IronPythonSdkFlavor();
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
Set<String> result = new TreeSet<>();
|
||||
String root = System.getenv("ProgramFiles(x86)");
|
||||
if (root == null) {
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -34,7 +37,7 @@ public class MacPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
private static final String[] POSSIBLE_BINARY_NAMES = {"python", "python2", "python3"};
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
Set<String> candidates = new HashSet<>();
|
||||
collectPythonInstallations("/Library/Frameworks/Python.framework/Versions", candidates);
|
||||
collectPythonInstallations("/System/Library/Frameworks/Python.framework/Versions", candidates);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.remote.RemoteFile;
|
||||
import icons.PythonIcons;
|
||||
@@ -37,7 +38,7 @@ public class PyRemoteSdkFlavor extends CPythonSdkFlavor {
|
||||
public static PyRemoteSdkFlavor INSTANCE = new PyRemoteSdkFlavor();
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkAdditionalData;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
@@ -70,7 +71,15 @@ public abstract class PythonSdkFlavor {
|
||||
PythonEnvUtil.addToPythonPath(envs, pythonPathList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #suggestHomePaths(Module)}. To be removed in 2019.2.
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<String> suggestHomePaths() {
|
||||
return suggestHomePaths(null);
|
||||
}
|
||||
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -36,7 +38,7 @@ public class UnixPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
public static final UnixPythonSdkFlavor INSTANCE = new UnixPythonSdkFlavor();
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
Set<String> candidates = new HashSet<>();
|
||||
collectUnixPythons("/usr/bin", candidates);
|
||||
return candidates;
|
||||
|
||||
@@ -15,18 +15,13 @@
|
||||
*/
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
import com.jetbrains.python.sdk.PySdkExtKt;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import icons.PythonIcons;
|
||||
@@ -50,26 +45,25 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor {
|
||||
public static VirtualEnvSdkFlavor INSTANCE = new VirtualEnvSdkFlavor();
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
|
||||
List<String> candidates = new ArrayList<>();
|
||||
if (project != null) {
|
||||
for (Module module : ModuleUtil.getModulesOfType(project, PythonModuleTypeBase.getInstance())) {
|
||||
final VirtualFile baseDir = PySdkExtKt.getBaseDir(module);
|
||||
if (baseDir != null) {
|
||||
candidates.addAll(findInDirectory(baseDir));
|
||||
}
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
final List<String> candidates = new ArrayList<>();
|
||||
if (module != null) {
|
||||
final VirtualFile baseDir = PySdkExtKt.getBaseDir(module);
|
||||
if (baseDir != null) {
|
||||
candidates.addAll(findInDirectory(baseDir));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final VirtualFile path = getDefaultLocation();
|
||||
if (path != null)
|
||||
if (path != null) {
|
||||
candidates.addAll(findInDirectory(path));
|
||||
}
|
||||
|
||||
final VirtualFile pyEnvLocation = getPyEnvDefaultLocations();
|
||||
if (pyEnvLocation != null) {
|
||||
candidates.addAll(findInDirectory(pyEnvLocation));
|
||||
}
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.sdk.flavors;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -23,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -48,7 +50,7 @@ public final class WinPythonSdkFlavor extends CPythonSdkFlavor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> suggestHomePaths() {
|
||||
public Collection<String> suggestHomePaths(@Nullable Module module) {
|
||||
Set<String> candidates = new TreeSet<>();
|
||||
findInCandidatePaths(candidates, "python.exe", "jython.bat", "pypy.exe");
|
||||
findInstallations(candidates, "python.exe", PythonHelpersLocator.getHelpersRoot().getParent());
|
||||
|
||||
@@ -44,7 +44,7 @@ class PyAddPipEnvPanel(private val project: Project?,
|
||||
|
||||
private val moduleField: JComboBox<Module>
|
||||
|
||||
private val baseSdkField = PySdkPathChoosingComboBox(findBaseSdks(existingSdks), null).apply {
|
||||
private val baseSdkField = PySdkPathChoosingComboBox(findBaseSdks(existingSdks, module), null).apply {
|
||||
val preferredSdkPath = PySdkSettings.instance.preferredVirtualEnvBaseSdk
|
||||
val detectedPreferredSdk = items.find { it.homePath == preferredSdkPath }
|
||||
selectedSdk = when {
|
||||
|
||||
Reference in New Issue
Block a user