From 17c8522684fc58c67cb185d02b3dbff01864d8a9 Mon Sep 17 00:00:00 2001 From: Vitaly Legchilkin Date: Tue, 17 Mar 2026 14:28:57 +0100 Subject: [PATCH] PY-88280 Extract autoConfigureSdkIfNeeded and simplify SDK auto-configuration - Add autoConfigureSdkIfNeeded to sdkSuggestionTools that waits for project model and uses the global mutex - Add early return in getModuleInfo when SDK is already configured - Simplify ModulesSdkConfigurator to use autoConfigureSdkIfNeeded - Simplify InterpreterSettingsQuickFix to use autoConfigureSdkIfNeeded - Remove SDK-configured notification from PyProjectSdkConfiguration (cherry picked from commit f1423427eeb433d379519e3b9d1af00b46fc869d) GitOrigin-RevId: b81353d3af62f2d1f694d8c0d470d4495a01c989 --- .../pyproject/model/api/sdkSuggestionTools.kt | 54 +++++++- .../src/impl/ModulesSdkConfigurator.kt | 80 +++--------- .../InterpreterSettingsQuickFix.kt | 121 +++++++----------- .../PyProjectSdkConfiguration.kt | 39 +----- 4 files changed, 118 insertions(+), 176 deletions(-) diff --git a/python/python-pyproject/src/com/intellij/python/pyproject/model/api/sdkSuggestionTools.kt b/python/python-pyproject/src/com/intellij/python/pyproject/model/api/sdkSuggestionTools.kt index e043e1431c31..dcba578af4c4 100644 --- a/python/python-pyproject/src/com/intellij/python/pyproject/model/api/sdkSuggestionTools.kt +++ b/python/python-pyproject/src/com/intellij/python/pyproject/model/api/sdkSuggestionTools.kt @@ -2,13 +2,23 @@ package com.intellij.python.pyproject.model.api import com.intellij.openapi.module.Module import com.intellij.openapi.project.guessModuleDir +import com.intellij.openapi.projectRoots.Sdk import com.intellij.python.common.tools.ToolId import com.intellij.python.pyproject.model.internal.suggestSdkImpl +import com.jetbrains.python.errorProcessing.PyResult +import com.jetbrains.python.onSuccess import com.jetbrains.python.sdk.configuration.CreateSdkInfo import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension import com.jetbrains.python.sdk.configuration.findPythonVirtualEnvironments +import com.jetbrains.python.sdk.configuration.getSdkCreator +import com.jetbrains.python.sdk.findPythonSdk +import com.jetbrains.python.sdk.legacy.PythonSdkUtil +import com.jetbrains.python.sdk.pythonSdk +import com.jetbrains.python.sdk.pythonSdkConfigurationMutex +import com.jetbrains.python.sdk.setAssociationToModule import com.jetbrains.python.venvReader.Directory +import org.jetbrains.annotations.ApiStatus sealed interface SuggestedSdk { @@ -33,11 +43,19 @@ suspend fun Module.suggestSdk(): SuggestedSdk? = suggestSdkImpl(this) /** - * For multiple calls, pull [configuratorsByTool] up not to create it each time + * Suggests an [ModuleCreateInfo] for this module, or returns `null` if the module + * already has a Python SDK or is not a Python module. + * + * Suspends until the project model is fully loaded (via [findPythonSdk]) before checking, + * so it is safe to call during startup without risking a false positive from a stale SDK table. + * + * For multiple calls, pull [configuratorsByTool] up not to create it each time. */ suspend fun Module.getModuleInfo( configuratorsByTool: Map = PyProjectSdkConfigurationExtension.createMap(), ): ModuleCreateInfo? { // Save on module level + findPythonSdk()?.let { return null } + val venvsInModule = findPythonVirtualEnvironments() val bestProposalFromTools = PyProjectSdkConfigurationExtension.findAllSortedForModule(this, venvsInModule).firstOrNull() @@ -76,3 +94,37 @@ sealed interface ModuleCreateInfo { private fun CreateSdkInfoWithTool.asDTO(moduleDir: Directory?): ModuleCreateInfo = ModuleCreateInfo.CreateSdkInfoWrapper(createSdkInfo, toolId, moduleDir) + + +/** + * Auto-configures a Python SDK for the module if one doesn't already exist. + * + * Waits for the SDK table to load (to avoid overwriting a persisted SDK that hasn't resolved yet), + * then detects the best SDK using [getModuleInfo] and assigns it to the module. + * + * Returns the configured SDK, or `null` if no SDK could be configured. + */ +@ApiStatus.Internal +suspend fun Module.autoConfigureSdkIfNeeded(): PyResult? = pythonSdkConfigurationMutex.withLock { + val moduleInfo = getModuleInfo() ?: return@withLock null + + when (moduleInfo) { + is ModuleCreateInfo.CreateSdkInfoWrapper -> { + when (moduleInfo.createSdkInfo) { + is CreateSdkInfo.ExistingEnv -> { + moduleInfo.createSdkInfo.getSdkCreator(this).createSdk().onSuccess {sdk -> + pythonSdk = sdk + sdk.setAssociationToModule(this) + } + } + is CreateSdkInfo.WillCreateEnv, is CreateSdkInfo.WillInstallTool -> null + } + } + is ModuleCreateInfo.SameAs -> { + moduleInfo.parentModule.findPythonSdk()?.let { parentSdk -> + pythonSdk = parentSdk + PyResult.success(parentSdk) + } + } + } +} diff --git a/python/python-sdk-configurator/backend/src/impl/ModulesSdkConfigurator.kt b/python/python-sdk-configurator/backend/src/impl/ModulesSdkConfigurator.kt index b788ed975806..2aea5666ea4e 100644 --- a/python/python-sdk-configurator/backend/src/impl/ModulesSdkConfigurator.kt +++ b/python/python-sdk-configurator/backend/src/impl/ModulesSdkConfigurator.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.util.removeUserData import com.intellij.platform.ide.progress.withBackgroundProgress import com.intellij.python.pyproject.model.api.ModuleCreateInfo import com.intellij.python.pyproject.model.api.SuggestedSdk +import com.intellij.python.pyproject.model.api.autoConfigureSdkIfNeeded import com.intellij.python.pyproject.model.api.getModuleInfo import com.intellij.python.pyproject.model.api.suggestSdk import com.intellij.python.sdkConfigurator.backend.impl.ModulesSdkConfigurator.Companion.create @@ -24,9 +25,10 @@ import com.jetbrains.python.orLogException import com.jetbrains.python.sdk.configuration.CreateSdkInfo import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension import com.jetbrains.python.sdk.configuration.createSdk -import com.jetbrains.python.sdk.configuration.getSdkCreator +import com.jetbrains.python.sdk.findPythonSdk import com.jetbrains.python.sdk.getOrCreateAdditionalData import com.jetbrains.python.sdk.legacy.PythonSdkUtil +import com.jetbrains.python.sdk.pythonSdkConfigurationMutex import com.jetbrains.python.sdk.pythonSdk import com.jetbrains.python.sdk.setAssociationToPath import kotlinx.collections.immutable.toPersistentList @@ -111,7 +113,7 @@ internal class ModulesSdkConfigurator private constructor( withBackgroundProgress(project, PySdkConfiguratorBundle.message("intellij.python.sdk.looking")) { val tools = PyProjectSdkConfigurationExtension.createMap() val now = System.currentTimeMillis() - val resultDef = project.modules.filter { PythonSdkUtil.findPythonSdk(it) == null }.map { module -> + val resultDef = project.modules.filter { it.findPythonSdk() != null }.map { module -> async { val moduleInfo = module.getModuleInfo(tools) ?: return@async null Pair(module, moduleInfo) @@ -136,7 +138,7 @@ internal class ModulesSdkConfigurator private constructor( * Errors are logged. * */ - suspend fun configureSdks(modulesOnly: Set) { + suspend fun configureSdks(modulesOnly: Set) = pythonSdkConfigurationMutex.withLock { withContext(Dispatchers.Default) { val modulesMap = project.modules.associateBy { it.name } val modulesWithSameSdk = mutableMapOf() @@ -190,78 +192,28 @@ internal class ModulesSdkConfigurator private constructor( @ApiStatus.Internal // Opened for tests only: we can't put tests here because configurators are in communuty.impl suspend fun configureSdkAutomatically(project: Project): Unit = withContext(Dispatchers.Default) { val moduleService = PyModuleService.getInstance(project) - val modules = project.modules.filter { moduleService.isPythonModule(it) } + val pythonModules = project.modules.filter { moduleService.isPythonModule(it) } - when (modules.size) { + when (pythonModules.size) { 0 -> return@withContext - 1 -> { // Single-module project, associate first module only - val module = modules.first() - if (PythonSdkUtil.findPythonSdk(module) != null) return@withContext // Already has SDK - configureSdkForModuleAutomatically(module, createEnvIfNeeded = false) - } - else -> { // Multi-module project, only associate workspace members - val modulesToSdk = modules.filter { PythonSdkUtil.findPythonSdk(it) == null }.associateWith { it.suggestSdk() } - for ((module, sdkSuggestion) in modulesToSdk) { + 1 -> pythonModules.first().autoConfigureSdkIfNeeded()?.orLogException(logger) + else -> pythonSdkConfigurationMutex.withLock { + for (module in pythonModules) { + if (module.findPythonSdk() != null) continue + val sdkSuggestion = module.suggestSdk() when (sdkSuggestion) { + is SuggestedSdk.SameAs -> { + val parentSdk = PythonSdkUtil.findPythonSdk(sdkSuggestion.parentModule) ?: continue + module.pythonSdk = parentSdk + } is SuggestedSdk.PyProjectIndependent, null -> { logger.trace { "${module.name} skipped in multimodule project autoconfig" } } - is SuggestedSdk.SameAs -> { - setModuleSdkAsParent(parentModule = sdkSuggestion.parentModule, module = module) - } } } } } } -private suspend fun configureSdkForModuleAutomatically(module: Module, createEnvIfNeeded: Boolean) { - when (val moduleInfo = module.getModuleInfo()) { - is ModuleCreateInfo.CreateSdkInfoWrapper -> { - when (val info = moduleInfo.createSdkInfo) { - is CreateSdkInfo.ExistingEnv -> { - info.createAndSetToModule(module) - } - is CreateSdkInfo.WillCreateEnv -> { - if (createEnvIfNeeded) { - info.createAndSetToModule(module) - } - else { - logger.trace { "${module.name} can't be configured automatically: no venv for ${moduleInfo.toolId}" } - } - } - is CreateSdkInfo.WillInstallTool -> logger.trace { "${module.name} can't be configured automatically: no tool installed - ${moduleInfo.toolId}" } - } - } - is ModuleCreateInfo.SameAs -> { - val parentModule = moduleInfo.parentModule - setModuleSdkAsParent(parentModule = parentModule, module = module) - } - null -> Unit - } -} - -private suspend fun CreateSdkInfo.createAndSetToModule(module: Module) { - when (val r = getSdkCreator(module).createSdk()) { - is Result.Failure -> { - logger.trace { "Failed to create sdk for ${module.name} : ${r.error}" } - } - is Result.Success -> { - val sdk = r.result - module.pythonSdk = sdk - logger.trace { "SDK creation result for ${module.name} : $sdk" } - } - } -} - -private fun setModuleSdkAsParent( - parentModule: Module, - module: Module, -) { - val parentSdk = PythonSdkUtil.findPythonSdk(parentModule) ?: return - logger.trace { "${module.name} seeds the same sdk as ${parentModule} : ${parentSdk}" } - module.pythonSdk = parentSdk -} - private val logger = fileLogger() diff --git a/python/src/com/jetbrains/python/inspections/interpreter/InterpreterSettingsQuickFix.kt b/python/src/com/jetbrains/python/inspections/interpreter/InterpreterSettingsQuickFix.kt index 6ee9543a13ca..354cfedbe90d 100644 --- a/python/src/com/jetbrains/python/inspections/interpreter/InterpreterSettingsQuickFix.kt +++ b/python/src/com/jetbrains/python/inspections/interpreter/InterpreterSettingsQuickFix.kt @@ -18,37 +18,34 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.vfs.newvfs.RefreshQueue import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService +import com.intellij.openapi.ui.popup.JBPopup +import com.intellij.openapi.ui.popup.JBPopupFactory +import com.intellij.openapi.util.use +import com.intellij.openapi.vfs.newvfs.RefreshQueue +import com.intellij.platform.ide.progress.withBackgroundProgress +import com.intellij.psi.PsiFile import com.intellij.python.common.tools.ToolId import com.intellij.python.pyproject.model.api.ModuleCreateInfo +import com.intellij.python.pyproject.model.api.autoConfigureSdkIfNeeded import com.intellij.python.pyproject.model.api.getModuleInfo -import com.intellij.psi.PsiFile +import com.intellij.ui.components.ActionLink +import com.intellij.ui.components.DropDownLink import com.intellij.util.PlatformUtils import com.jetbrains.python.PyBundle import com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable -import com.jetbrains.python.Result import com.jetbrains.python.inspections.InspectionRunnerResult -import com.intellij.openapi.ui.popup.JBPopup -import com.intellij.openapi.ui.popup.JBPopupFactory -import com.intellij.ui.components.ActionLink -import com.intellij.ui.components.DropDownLink +import com.jetbrains.python.orLogException import com.jetbrains.python.sdk.ModuleOrProject import com.jetbrains.python.sdk.collectAddInterpreterActions -import com.intellij.openapi.util.use -import com.intellij.platform.ide.progress.withBackgroundProgress import com.jetbrains.python.sdk.configuration.CreateSdkInfo import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool import com.jetbrains.python.sdk.configuration.PyProjectSdkConfiguration -import com.jetbrains.python.sdk.configuration.createSdk -import com.jetbrains.python.sdk.pythonSdk -import com.jetbrains.python.sdk.switchToSdk -import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService -import com.jetbrains.python.sdk.setAssociationToModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext import org.jetbrains.annotations.ApiStatus +import java.nio.file.Path /** * Executor that accepts at most one concurrent task. @@ -76,6 +73,12 @@ interface BusyGuardExecutor { * and rendered inside [PyInterpreterNotificationProvider]. * Long-running work (SDK creation, tool installation) must be submitted through the supplied [BusyGuardExecutor] * so that all notification panels share the same busy state. + * + * **WARNING:** Implementations must NOT hold strong references to [Module] or [Project] in their fields. + * Instances are cached by [PyAsyncFileInspectionRunner] with the Module as a weak key. + * A strong reference from the fix back to the Module prevents the weak key from being collected, + * causing a project leak after the project is closed. Use the [module] and [project] parameters + * passed to [createActionLink] instead. */ @ApiStatus.Internal interface InterpreterFix { @@ -128,7 +131,7 @@ internal fun createInterpreterCacheLoader(): suspend (Module) -> InspectionRunne val moduleCreateInfo = module.getModuleInfo() val fixes = buildList { getSuitableSdkFix(module, moduleCreateInfo)?.let { add(it) } - add(ConfigureInterpreterFix()) + moduleCreateInfo?.let { add(ConfigureInterpreterFix()) } } val shouldCache = when (moduleCreateInfo) { is ModuleCreateInfo.SameAs -> false @@ -150,19 +153,14 @@ internal class ConfigureInterpreterFix : InterpreterFix { override fun createActionLink(module: Module, project: Project, psiFile: PsiFile, executor: BusyGuardExecutor): ActionLink { return DropDownLink(PyBundle.message("python.sdk.custom.environment")) { val context = DataManager.getInstance().getDataContext(it) - createAddInterpreterPopup(module, context, executor) + createAddInterpreterPopup(module, context) } } companion object { - fun createAddInterpreterPopup(module: Module, context: DataContext, executor: BusyGuardExecutor): JBPopup { - val currentSdk = module.pythonSdk + fun createAddInterpreterPopup(module: Module, context: DataContext): JBPopup { val group = DefaultActionGroup() - group.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { sdk -> - executor.execute { - withContext(Dispatchers.IO) { switchToSdk(module, sdk, currentSdk) } - } - }) + group.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { }) ActionManager.getInstance().getAction("Python.NewInterpreter.Extra")?.let { group.add(it) } @@ -177,15 +175,18 @@ internal class ConfigureInterpreterFix : InterpreterFix { } } -private class UseProvidedInterpreterFix(private val myModule: Module, private val myCreateSdkInfo: CreateSdkInfoWithTool) : InterpreterFix { +private class UseProvidedInterpreterFix( + private val myCreateSdkInfo: CreateSdkInfoWithTool, + private val modulePath: Path?, +) : InterpreterFix { override fun createActionLink(module: Module, project: Project, psiFile: PsiFile, executor: BusyGuardExecutor): ActionLink { return ActionLink(myCreateSdkInfo.createSdkInfo.intentionName) { executor.execute { - val lifetime = PyProjectSdkConfiguration.suppressTipAndInspectionsFor(myModule, myCreateSdkInfo.toolId.id) + val lifetime = PyProjectSdkConfiguration.suppressTipAndInspectionsFor(module, myCreateSdkInfo.toolId.id) withBackgroundProgress(project, myCreateSdkInfo.createSdkInfo.intentionName, false) { - lifetime.use { PyProjectSdkConfiguration.setSdkUsingCreateSdkInfo(myModule, myCreateSdkInfo) } + lifetime.use { PyProjectSdkConfiguration.setSdkUsingCreateSdkInfo(module, myCreateSdkInfo) } } - RefreshQueue.getInstance().refresh(recursive = false, files = ModuleRootManager.getInstance(myModule).contentRoots.toList()) + RefreshQueue.getInstance().refresh(recursive = false, files = ModuleRootManager.getInstance(module).contentRoots.toList()) } } } @@ -208,59 +209,27 @@ private class SuggestToolInstallationFix( } } -private suspend fun Module.getQuickFixBySdkSuggestion(i: ModuleCreateInfo?): FindQuickFixResult = when (i) { - is ModuleCreateInfo.CreateSdkInfoWrapper -> { - when (val createSdkInfo = i.createSdkInfo) { - is CreateSdkInfo.ExistingEnv -> { - logger.trace { "$this: Files already exist, just create sn SDK" } - when (val creationResult = createSdkInfo.createSdk(module = this)) { - is Result.Failure -> { - logger.warn("Can't create SDK for $this : ${creationResult.error}") - FindQuickFixResult.NoSuggestion - } - is Result.Success -> { - val sdk = creationResult.result - logger.trace { "$this: sdk $sdk created" } - pythonSdk = sdk // SDK can't be null - project.pySdkService.persistSdk(sdk) - sdk.setAssociationToModule(this) - FindQuickFixResult.SdkAppliedAutomatically(sdk) - } +private suspend fun Module.getQuickFixBySdkSuggestion(i: ModuleCreateInfo?): FindQuickFixResult { + // Try auto-configure (waits for SDK table, handles ExistingEnv and SameAs) + autoConfigureSdkIfNeeded()?.orLogException(logger)?.let { return FindQuickFixResult.SdkAppliedAutomatically(it) } + + // No existing env — show user fix for WillCreateEnv / WillInstallTool + return when (i) { + is ModuleCreateInfo.CreateSdkInfoWrapper -> { + when (val createSdkInfo = i.createSdkInfo) { + is CreateSdkInfo.ExistingEnv -> FindQuickFixResult.NoSuggestion // already handled by autoConfigureSdkIfNeeded + is CreateSdkInfo.WillCreateEnv -> { + logger.trace { "$this: Ask user as it is a heavy operation" } + FindQuickFixResult.ShowUserFix(UseProvidedInterpreterFix(CreateSdkInfoWithTool(createSdkInfo, i.toolId), i.moduleDir)) + } + is CreateSdkInfo.WillInstallTool -> { + logger.trace { "$this: Tool installation will be suggested to the user" } + FindQuickFixResult.ShowUserFix(SuggestToolInstallationFix(this, createSdkInfo, i.toolId)) } } - is CreateSdkInfo.WillCreateEnv -> { - logger.trace { "$this: Ask user as it is a heavy operation" } - val tool = CreateSdkInfoWithTool(createSdkInfo, i.toolId) - FindQuickFixResult.ShowUserFix(UseProvidedInterpreterFix(this, tool)) - } - is CreateSdkInfo.WillInstallTool -> { - logger.trace { "$this: Tool installation will be suggested to the user" } - FindQuickFixResult.ShowUserFix(SuggestToolInstallationFix(this, createSdkInfo, i.toolId)) - } } + is ModuleCreateInfo.SameAs, null -> FindQuickFixResult.NoSuggestion // SameAs already handled by autoConfigureSdkIfNeeded } - is ModuleCreateInfo.SameAs -> { - logger.trace { "$this: Same as parent" } - i.parentModule.pythonSdk?.let { parentModuleSdk -> - logger.trace { "$this: Parent has SDK $parentModuleSdk" } - pythonSdk = parentModuleSdk - FindQuickFixResult.SdkAppliedAutomatically(parentModuleSdk) - } ?: - // Try to find SDK for parent otherwise - when (val parentResult = i.parentModule.getQuickFixBySdkSuggestion(i.parentModule.getModuleInfo())) { - is FindQuickFixResult.SdkAppliedAutomatically -> { - val parentModuleSdk = parentResult.sdk - logger.trace { "$this: Parent has SDK $parentModuleSdk" } - pythonSdk = parentModuleSdk - FindQuickFixResult.SdkAppliedAutomatically(parentModuleSdk) - } - FindQuickFixResult.NoSuggestion, is FindQuickFixResult.ShowUserFix -> { - logger.trace { "$this: Parent SDK can't be created ($parentResult), so is ours" } - parentResult - } - } - } - null -> FindQuickFixResult.NoSuggestion } private sealed interface FindQuickFixResult { diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt index 51ac54a26c00..61386bae8255 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt @@ -1,36 +1,25 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.python.sdk.configuration -import com.intellij.notification.NotificationAction -import com.intellij.notification.NotificationGroupManager -import com.intellij.notification.NotificationType import com.intellij.openapi.Disposable -import com.intellij.openapi.application.EDT - import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project -import com.intellij.openapi.project.isNotificationSilentMode import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.util.Disposer - -import com.intellij.openapi.wm.ex.WelcomeScreenProjectProvider - import com.intellij.python.community.services.systemPython.SystemPythonService import com.jetbrains.python.PyBundle import com.jetbrains.python.PythonPluginDisposable import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.errorProcessing.emit -import com.jetbrains.python.sdk.PySdkPopupFactory import com.jetbrains.python.sdk.configuration.suppressors.PyPackageRequirementsInspectionSuppressor import com.jetbrains.python.sdk.configuration.suppressors.TipOfTheDaySuppressor import com.jetbrains.python.sdk.configurePythonSdk -import com.jetbrains.python.sdk.impl.PySdkBundle import com.jetbrains.python.sdk.installExecutableViaPythonScript -import com.jetbrains.python.statistics.ConfiguredPythonInterpreterIdsHolder.Companion.SDK_HAS_BEEN_CONFIGURED_AS_THE_PROJECT_INTERPRETER import com.jetbrains.python.util.ShowingMessageErrorSync import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import org.jetbrains.annotations.ApiStatus import java.nio.file.Path object PyProjectSdkConfiguration { @@ -56,20 +45,18 @@ object PyProjectSdkConfiguration { return@withContext true } - setReadyToUseSdk(module.project, module, sdk) + configurePythonSdk(module.project, module, sdk) thisLogger().debug("Successfully configured sdk using ${createSdkInfoWithTool.toolId}") true } - suspend fun setReadyToUseSdk(project: Project, module: Module, sdk: Sdk) { + @ApiStatus.Obsolete + fun setReadyToUseSdk(project: Project, module: Module, sdk: Sdk) { if (module.isDisposed) { return } configurePythonSdk(project, module, sdk) - withContext(Dispatchers.EDT) { - notifyAboutConfiguredSdk(project, module, sdk) - } } fun suppressTipAndInspectionsFor(module: Module, toolName: String): Disposable { @@ -86,22 +73,4 @@ object PyProjectSdkConfiguration { PythonSdkCreationWaiter.register(module, lifetime) return lifetime } - - private fun notifyAboutConfiguredSdk(project: Project, module: Module, sdk: Sdk) { - if (isNotificationSilentMode(project) || WelcomeScreenProjectProvider.isWelcomeScreenProject(project)) return - NotificationGroupManager.getInstance().getNotificationGroup("ConfiguredPythonInterpreter") - .createNotification( - content = PyBundle.message("sdk.has.been.configured.as.the.project.interpreter", sdk.name), - type = NotificationType.INFORMATION - ) - .setDisplayId(SDK_HAS_BEEN_CONFIGURED_AS_THE_PROJECT_INTERPRETER) - .apply { - val configureSdkAction = NotificationAction.createSimpleExpiring(PySdkBundle.message("python.configure.interpreter.action")) { - PySdkPopupFactory.createAndShow(module) - } - - addAction(configureSdkAction) - notify(project) - } - } }