PY-76416: Filter out venvs from base pythons in SDK creation dialog.

Base Pythons are system-wide pythons, not venvs.
`PythonSdkFlavor.isPlatformIndependent` is `false` for base pythons.

Venvs can only be created on top of base pythons and not on top of other venvs.

We detect all pythons (even venvs in `~/.virtualenvs` e.t.c.) because we might need them in "Select Existing Interpreter" window, but since for "Create New Venv" we can only use base pythons, we use flavor to filter.


(cherry picked from commit 7b4719b821243a4d97304cfa1d106439b11f63b1)

KT-MR-18675

GitOrigin-RevId: e001e8f593b7a964067cbd04fcc3fd22ea8ec4a2
This commit is contained in:
Ilya.Kazakevich
2024-10-28 21:34:36 +01:00
committed by intellij-monorepo-bot
parent 12357b95f7
commit 81cdb86823

View File

@@ -4,7 +4,6 @@ package com.jetbrains.python.sdk.add.v2
import com.intellij.execution.target.TargetEnvironmentConfiguration import com.intellij.execution.target.TargetEnvironmentConfiguration
import com.intellij.ide.util.PropertiesComponent import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.application.EDT import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.diagnostic.getOrLogException import com.intellij.openapi.diagnostic.getOrLogException
import com.intellij.openapi.fileChooser.FileChooser import com.intellij.openapi.fileChooser.FileChooser
import com.intellij.openapi.observable.properties.ObservableMutableProperty import com.intellij.openapi.observable.properties.ObservableMutableProperty
@@ -26,8 +25,11 @@ import com.jetbrains.python.sdk.flavors.conda.PyCondaEnvIdentity
import com.jetbrains.python.sdk.pipenv.pipEnvPath import com.jetbrains.python.sdk.pipenv.pipEnvPath
import com.jetbrains.python.sdk.poetry.poetryPath import com.jetbrains.python.sdk.poetry.poetryPath
import com.jetbrains.python.util.ErrorSink import com.jetbrains.python.util.ErrorSink
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.plus
import kotlinx.coroutines.withContext
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.pathString import kotlin.io.path.pathString
@@ -61,6 +63,7 @@ abstract class PythonAddInterpreterModel(params: PyInterpreterModelParams) {
.stateIn(scope + uiContext, started = SharingStarted.Eagerly, initialValue = emptyList()) .stateIn(scope + uiContext, started = SharingStarted.Eagerly, initialValue = emptyList())
val baseInterpreters: StateFlow<List<PythonSelectableInterpreter>> = allInterpreters val baseInterpreters: StateFlow<List<PythonSelectableInterpreter>> = allInterpreters
.map { it.filter { it.isBasePython() } }
.mapLatest { .mapLatest {
it.filter { it !is ExistingSelectableInterpreter || it.isSystemWide } + installable it.filter { it !is ExistingSelectableInterpreter || it.isSystemWide } + installable
} }
@@ -229,8 +232,15 @@ class PythonLocalAddInterpreterModel(params: PyInterpreterModelParams)
} }
// todo does it need target configuration
sealed class PythonSelectableInterpreter { sealed class PythonSelectableInterpreter {
/**
* Base python is some system python (not venv) which can be used as a base for venv.
* In terms of flavors we call it __not__ [PythonSdkFlavor.isPlatformIndependent]
*/
open suspend fun isBasePython(): Boolean = withContext(Dispatchers.IO) {
PythonSdkFlavor.tryDetectFlavorByLocalPath(homePath)?.isPlatformIndependent == false
}
abstract val homePath: String abstract val homePath: String
abstract val languageLevel: LanguageLevel abstract val languageLevel: LanguageLevel
override fun toString(): String = override fun toString(): String =
@@ -238,6 +248,10 @@ sealed class PythonSelectableInterpreter {
} }
class ExistingSelectableInterpreter(val sdk: Sdk, override val languageLevel: LanguageLevel, val isSystemWide: Boolean) : PythonSelectableInterpreter() { class ExistingSelectableInterpreter(val sdk: Sdk, override val languageLevel: LanguageLevel, val isSystemWide: Boolean) : PythonSelectableInterpreter() {
override suspend fun isBasePython(): Boolean = withContext(Dispatchers.IO) {
!sdk.sdkFlavor.isPlatformIndependent
}
override val homePath = sdk.homePath!! // todo is it safe override val homePath = sdk.homePath!! // todo is it safe
} }
@@ -246,6 +260,7 @@ class DetectedSelectableInterpreter(override val homePath: String, override val
class ManuallyAddedSelectableInterpreter(override val homePath: String, override val languageLevel: LanguageLevel) : PythonSelectableInterpreter() class ManuallyAddedSelectableInterpreter(override val homePath: String, override val languageLevel: LanguageLevel) : PythonSelectableInterpreter()
class InstallableSelectableInterpreter(val sdk: PySdkToInstall) : PythonSelectableInterpreter() { class InstallableSelectableInterpreter(val sdk: PySdkToInstall) : PythonSelectableInterpreter() {
override suspend fun isBasePython(): Boolean = true
override val homePath: String = "" override val homePath: String = ""
override val languageLevel = PySdkUtil.getLanguageLevelForSdk(sdk) override val languageLevel = PySdkUtil.getLanguageLevelForSdk(sdk)
} }