diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml
index d58980868414..398164522c2a 100644
--- a/python/pluginResources/intellij.python.community.impl.xml
+++ b/python/pluginResources/intellij.python.community.impl.xml
@@ -123,6 +123,11 @@
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
+
+
+
+
- if (type in moduleSdksByTypes) {
- if (index != 0) group.addSeparator()
- group.addAll(moduleSdksByTypes
- .getValue(type)
- .filter {
- targetModuleSitsOn == null ||
- targetModuleSitsOn.codeCouldProbablyBeRunWithConfig(it.targetAdditionalData?.targetEnvironmentConfiguration)
- }
- .mapNotNull { model.findSdk(it) }
- .map { SwitchToSdkAction(it, currentSdk) })
+ if (index != 0) group.addSeparator()
+ val sdksByType = moduleSdksByTypes[type]?.distinctBy {
+ it.sdkAdditionalData?.javaClass to it.homePath
+ } ?: return@forEachIndexed
+
+ val uniqueSdks = if (type == PyRenderedSdkType.REMOTE) {
+ sdksByType.filter {
+ targetModuleSitsOn == null ||
+ targetModuleSitsOn.codeCouldProbablyBeRunWithConfig(it.targetAdditionalData?.targetEnvironmentConfiguration)
+ }
}
+ else {
+ sdksByType.distinctBy { it.sdkAdditionalData?.javaClass to it.homePath }
+ }
+
+ val actions = uniqueSdks.map { SwitchToSdkAction(it, currentSdk) }
+ group.addAll(actions)
}
if (moduleSdksByTypes.isNotEmpty()) group.addSeparator()
val addNewInterpreterPopupGroup = DefaultActionGroup(PyBundle.message("python.sdk.action.add.new.interpreter.text"), true)
- addNewInterpreterPopupGroup.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { sdk ->
- SlowOperations.knownIssue("PY-76167").use {
- switchToSdk(module, sdk, currentSdk)
- }
- })
+ addNewInterpreterPopupGroup.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { })
ActionManager.getInstance().getAction("Python.NewInterpreter.Extra")?.let {
addNewInterpreterPopupGroup.add(it)
}
@@ -123,7 +124,7 @@ class PySdkPopupFactory(val module: Module) {
presentation.icon = icon(sdk)
}
- override fun actionPerformed(e: AnActionEvent) = switchToSdk(module, sdk, currentSdk)
+ override fun actionPerformed(e: AnActionEvent) = run { module.pythonSdk = sdk }
}
private inner class InterpreterSettingsAction : DumbAwareAction(PyBundle.messagePointer("python.sdk.popup.interpreter.settings")) {
diff --git a/python/src/com/jetbrains/python/sdk/PyTransferredSdkRoots.kt b/python/src/com/jetbrains/python/sdk/PyTransferredSdkRoots.kt
index 1a1b098b07ac..33434b2a7520 100644
--- a/python/src/com/jetbrains/python/sdk/PyTransferredSdkRoots.kt
+++ b/python/src/com/jetbrains/python/sdk/PyTransferredSdkRoots.kt
@@ -172,6 +172,32 @@ private fun updateRootsForModulesWithInheritedSdk(project: Project, sdk: Sdk?, a
}
}
+/**
+ * Handles transferred roots and virtualenv exclusion when a module's Python SDK changes.
+ * Registered as a listener for [PySdkListener.TOPIC].
+ *
+ * Note: cannot use the public [removeTransferredRoots] for `prevSdk` because its guard
+ * `module.pythonSdk == sdk` fails — by the time the listener fires, the SDK is already changed.
+ */
+internal class PySdkTransferredRootsListener : PySdkListener {
+ override fun moduleSdkUpdated(module: Module, prevSdk: Sdk?, newSdk: Sdk?) {
+ if (prevSdk != null) {
+ val oldPaths = getPathsToTransfer(prevSdk)
+ if (oldPaths.isNotEmpty()) {
+ runInEdt {
+ val rootsToRemove = TransferredRootsDetector(module.project).detect(module, oldPaths, oldPaths)
+ removeTransferredRoots(module, rootsToRemove)
+ }
+ }
+ }
+
+ if (newSdk != null) {
+ transferRoots(module, newSdk)
+ module.excludeInnerVirtualEnv(newSdk)
+ }
+ }
+}
+
private object ModuleRootAndDepOps {
val LOG = thisLogger()
}
diff --git a/python/src/com/jetbrains/python/sdk/evolution/advancedActions.kt b/python/src/com/jetbrains/python/sdk/evolution/advancedActions.kt
index 95ecc53c9519..29035260998e 100644
--- a/python/src/com/jetbrains/python/sdk/evolution/advancedActions.kt
+++ b/python/src/com/jetbrains/python/sdk/evolution/advancedActions.kt
@@ -7,12 +7,9 @@ import com.intellij.python.sdk.ui.evolution.ui.EvoSelectSdkProvider
import com.intellij.python.sdk.ui.evolution.ui.components.EvoTreeLazyNodeElement
import com.intellij.python.sdk.ui.evolution.ui.components.EvoTreeLeafElement
import com.intellij.python.sdk.ui.evolution.ui.components.EvoTreeSection
-import com.intellij.util.SlowOperations
import com.jetbrains.python.Result
import com.jetbrains.python.sdk.ModuleOrProject
import com.jetbrains.python.sdk.collectAddInterpreterActions
-import com.jetbrains.python.sdk.pythonSdk
-import com.jetbrains.python.sdk.switchToSdk
internal class AdvancedSelectSdkProvider() : EvoSelectSdkProvider {
@@ -21,11 +18,7 @@ internal class AdvancedSelectSdkProvider() : EvoSelectSdkProvider {
icon = AllIcons.Toolwindows.ToolWindowInternal
) {
- val baseIdeActions = collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(evoModuleSdk.module)) { sdk ->
- SlowOperations.knownIssue("PY-76167").use {
- switchToSdk(evoModuleSdk.module, sdk, evoModuleSdk.module.pythonSdk)
- }
- }
+ val baseIdeActions = collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(evoModuleSdk.module)) { }
val section = EvoTreeSection(
label = null,