mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Configure Python interpreter in background (PY-39541)
GitOrigin-RevId: b9a48a2a89320715cd3c3524269af7eea080487e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d66e0eec0e
commit
468aad6048
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python
|
||||
|
||||
import com.intellij.concurrency.SensitiveProgressWrapper
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
@@ -16,6 +17,7 @@ import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel
|
||||
import com.intellij.openapi.util.UserDataHolder
|
||||
import com.intellij.openapi.util.UserDataHolderBase
|
||||
import com.intellij.ui.AppUIUtil
|
||||
import com.jetbrains.python.sdk.*
|
||||
import com.jetbrains.python.sdk.pipenv.detectAndSetupPipEnv
|
||||
|
||||
@@ -33,22 +35,9 @@ class PythonSdkConfigurator {
|
||||
}
|
||||
|
||||
private fun findDetectedAssociatedEnvironment(module: Module, existingSdks: List<Sdk>, context: UserDataHolder): PyDetectedSdk? {
|
||||
// TODO: Move all interpreter detection away from EDT & use proper synchronization for that
|
||||
val progress = ProgressManager.getInstance()
|
||||
return progress.run(object : Task.WithResult<PyDetectedSdk?, Exception>(module.project,
|
||||
"Looking for Virtual Environments",
|
||||
false) {
|
||||
override fun compute(indicator: ProgressIndicator): PyDetectedSdk? {
|
||||
indicator.isIndeterminate = true
|
||||
detectVirtualEnvs(module, existingSdks, context).firstOrNull { it.isAssociatedWithModule(module) }?.let {
|
||||
return it
|
||||
}
|
||||
detectCondaEnvs(module, existingSdks, context).firstOrNull { it.isAssociatedWithModule(module) }?.let {
|
||||
return it
|
||||
}
|
||||
return null
|
||||
}
|
||||
})
|
||||
detectVirtualEnvs(module, existingSdks, context).firstOrNull { it.isAssociatedWithModule(module) }?.let { return it }
|
||||
detectCondaEnvs(module, existingSdks, context).firstOrNull { it.isAssociatedWithModule(module) }?.let { return it }
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getDefaultProjectSdk(): Sdk? {
|
||||
@@ -60,61 +49,92 @@ class PythonSdkConfigurator {
|
||||
|
||||
private fun findDetectedSystemWideSdk(module: Module?, existingSdks: List<Sdk>, context: UserDataHolder) =
|
||||
detectSystemWideSdks(module, existingSdks, context).firstOrNull()
|
||||
|
||||
private fun <T> guardIndicator(indicator: ProgressIndicator, computable: () -> T): T {
|
||||
return ProgressManager.getInstance().runProcess(computable, SensitiveProgressWrapper(indicator))
|
||||
}
|
||||
|
||||
private fun onEdt(project: Project, runnable: () -> Unit) = AppUIUtil.invokeOnEdt(Runnable { runnable() }, project.disposed)
|
||||
}
|
||||
|
||||
init {
|
||||
ApplicationManager.getApplication().messageBus.connect().subscribe(ProjectManager.TOPIC, object : ProjectManagerListener {
|
||||
override fun projectOpened(project: Project) {
|
||||
if (!project.isDefault) {
|
||||
configureSdk(project)
|
||||
}
|
||||
ProgressManager.getInstance().run(
|
||||
object : Task.Backgroundable(project, "Configuring a Python Interpreter", true) {
|
||||
override fun run(indicator: ProgressIndicator) = configureSdk(project, indicator)
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun configureSdk(project: Project) {
|
||||
private fun configureSdk(project: Project, indicator: ProgressIndicator) {
|
||||
indicator.isIndeterminate = true
|
||||
|
||||
if (project.isDefault || project.pythonSdk != null) return
|
||||
|
||||
val context = UserDataHolderBase()
|
||||
if (project.pythonSdk != null) {
|
||||
return
|
||||
}
|
||||
val module = ModuleManager.getInstance(project).modules.firstOrNull() ?: return
|
||||
val existingSdks = ProjectSdksModel().apply { reset(project) }.sdks.filter { it.sdkType is PythonSdkType }
|
||||
|
||||
findExistingAssociatedSdk(module, existingSdks)?.let {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
module.excludeInnerVirtualEnv(it)
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for the previously used interpreter"
|
||||
guardIndicator(indicator) { findExistingAssociatedSdk(module, existingSdks) }?.let {
|
||||
onEdt(project) {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
module.excludeInnerVirtualEnv(it)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
findDetectedAssociatedEnvironment(module, existingSdks, context)?.let {
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for a virtual environment related to the project"
|
||||
guardIndicator(indicator) { findDetectedAssociatedEnvironment(module, existingSdks, context) }?.let {
|
||||
val newSdk = it.setupAssociated(existingSdks, module.basePath) ?: return
|
||||
SdkConfigurationUtil.addSdk(newSdk)
|
||||
newSdk.associateWithModule(module, null)
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, newSdk)
|
||||
module.excludeInnerVirtualEnv(it)
|
||||
|
||||
onEdt(project) {
|
||||
SdkConfigurationUtil.addSdk(newSdk)
|
||||
newSdk.associateWithModule(module, null)
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, newSdk)
|
||||
module.excludeInnerVirtualEnv(it)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Introduce an extension for configuring a project via a Python SDK provider
|
||||
detectAndSetupPipEnv(project, module, existingSdks)?.let {
|
||||
SdkConfigurationUtil.addSdk(it)
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for a Pipfile"
|
||||
guardIndicator(indicator) { detectAndSetupPipEnv(project, module, existingSdks) }?.let {
|
||||
onEdt(project) {
|
||||
SdkConfigurationUtil.addSdk(it)
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
getDefaultProjectSdk()?.let {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for the default interpreter setting for a new project"
|
||||
guardIndicator(indicator) { getDefaultProjectSdk() }?.let {
|
||||
onEdt(project) { SdkConfigurationUtil.setDirectoryProjectSdk(project, it) }
|
||||
return
|
||||
}
|
||||
|
||||
findExistingSystemWideSdk(existingSdks)?.let {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, it)
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for the previously used system-wide interpreter"
|
||||
guardIndicator(indicator) { findExistingSystemWideSdk(existingSdks) }?.let {
|
||||
onEdt(project) { SdkConfigurationUtil.setDirectoryProjectSdk(project, it) }
|
||||
return
|
||||
}
|
||||
|
||||
findDetectedSystemWideSdk(module, existingSdks, context)?.let {
|
||||
SdkConfigurationUtil.createAndAddSDK(it.homePath!!, PythonSdkType.getInstance())?.apply {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, this)
|
||||
if (indicator.isCanceled) return
|
||||
indicator.text = "Looking for a system-wide interpreter"
|
||||
guardIndicator(indicator) { findDetectedSystemWideSdk(module, existingSdks, context) }?.let {
|
||||
onEdt(project) {
|
||||
SdkConfigurationUtil.createAndAddSDK(it.homePath!!, PythonSdkType.getInstance())?.apply {
|
||||
SdkConfigurationUtil.setDirectoryProjectSdk(project, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user