From 18fb6cb19324864dbe4479fb1ea6f5afd2a66e77 Mon Sep 17 00:00:00 2001 From: Konstantin Hudyakov Date: Tue, 15 Dec 2020 15:05:32 +0300 Subject: [PATCH] Extract virtual env creating logic to util class IDEA-CR-69125 GitOrigin-RevId: 9b7a3f1a9fd4589eb872d24ecde8203e3cf66f78 --- .../python/sdk/add/PyAddNewVirtualEnvPanel.kt | 44 ++---------- .../jetbrains/python/sdk/add/PyAddSdkPanel.kt | 14 ++-- .../PyProjectVirtualEnvConfiguration.kt | 68 +++++++++++++++++++ 3 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 python/src/com/jetbrains/python/sdk/configuration/PyProjectVirtualEnvConfiguration.kt diff --git a/python/src/com/jetbrains/python/sdk/add/PyAddNewVirtualEnvPanel.kt b/python/src/com/jetbrains/python/sdk/add/PyAddNewVirtualEnvPanel.kt index 12881f8cb1ed..3b46d0a97083 100644 --- a/python/src/com/jetbrains/python/sdk/add/PyAddNewVirtualEnvPanel.kt +++ b/python/src/com/jetbrains/python/sdk/add/PyAddNewVirtualEnvPanel.kt @@ -1,27 +1,22 @@ // Copyright 2000-2020 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.sdk.add -import com.intellij.execution.ExecutionException import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleUtil -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.progress.Task import com.intellij.openapi.project.Project -import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.util.UserDataHolder import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.ui.DocumentAdapter import com.intellij.ui.components.JBCheckBox import com.intellij.util.ui.FormBuilder import com.jetbrains.python.PyBundle import com.jetbrains.python.PySdkBundle -import com.jetbrains.python.packaging.PyPackageManager -import com.jetbrains.python.sdk.* +import com.jetbrains.python.sdk.PySdkSettings +import com.jetbrains.python.sdk.basePath +import com.jetbrains.python.sdk.configuration.PyProjectVirtualEnvConfiguration import icons.PythonIcons import org.jetbrains.annotations.SystemIndependent import java.awt.BorderLayout @@ -75,26 +70,9 @@ class PyAddNewVirtualEnvPanel(private val project: Project?, validateSdkComboBox(baseSdkField, this)) override fun getOrCreateSdk(): Sdk? { - val root = pathField.text - val baseSdk = installSdkIfNeeded(baseSdkField.selectedSdk, module, existingSdks, context) - if (baseSdk == null) return null - - val task = object : Task.WithResult(project, PySdkBundle.message("python.creating.venv.title"), false) { - override fun compute(indicator: ProgressIndicator): String { - indicator.isIndeterminate = true - val packageManager = PyPackageManager.getInstance(baseSdk) - return packageManager.createVirtualEnv(root, inheritSitePackagesField.isSelected) - } - } - val shared = makeSharedField.isSelected - val associatedPath = if (!shared) projectBasePath else null - val sdk = createSdkByGenerateTask(task, existingSdks, baseSdk, associatedPath, null) ?: return null - if (!shared) { - sdk.associateWithModule(module, newProjectPath) - } - moduleToExcludeSdkFrom(root, project)?.excludeInnerVirtualEnv(sdk) - PySdkSettings.instance.onVirtualEnvCreated(baseSdk, FileUtil.toSystemIndependentName(root), projectBasePath) - return sdk + return PyProjectVirtualEnvConfiguration.createVirtualEnvSynchronously(baseSdkField.selectedSdk, existingSdks, pathField.text, + newProjectPath, project, module, context, + inheritSitePackagesField.isSelected, makeSharedField.isSelected) } override fun addChangeListener(listener: Runnable) { @@ -106,16 +84,6 @@ class PyAddNewVirtualEnvPanel(private val project: Project?, baseSdkField.childComponent.addItemListener { listener.run() } } - private fun moduleToExcludeSdkFrom(path: String, project: Project?): Module? { - val possibleProjects = if (project != null) listOf(project) else ProjectManager.getInstance().openProjects.asList() - val rootFile = StandardFileSystems.local().refreshAndFindFileByPath(path) ?: return null - return possibleProjects - .asSequence() - .map { ModuleUtil.findModuleForFile(rootFile, it) } - .filterNotNull() - .firstOrNull() - } - private val projectBasePath: @SystemIndependent String? get() = newProjectPath ?: module?.basePath ?: project?.basePath } diff --git a/python/src/com/jetbrains/python/sdk/add/PyAddSdkPanel.kt b/python/src/com/jetbrains/python/sdk/add/PyAddSdkPanel.kt index 93008ee0a25c..65152cdf086d 100644 --- a/python/src/com/jetbrains/python/sdk/add/PyAddSdkPanel.kt +++ b/python/src/com/jetbrains/python/sdk/add/PyAddSdkPanel.kt @@ -26,12 +26,12 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.UserDataHolder -import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.jetbrains.python.PySdkBundle import com.jetbrains.python.newProject.steps.PyAddNewEnvironmentPanel import com.jetbrains.python.sdk.* import com.jetbrains.python.sdk.add.PyAddSdkDialogFlowAction.OK +import com.jetbrains.python.sdk.configuration.PyProjectVirtualEnvConfiguration import icons.PythonIcons import java.awt.Component import java.io.File @@ -162,14 +162,12 @@ fun addBaseInterpretersAsync(sdkComboBox: PySdkPathChoosingComboBox, { findBaseSdks(existingSdks, module, context).takeIf { it.isNotEmpty() } ?: getSdksToInstall() }, { sdkComboBox.apply { - val preferredSdkPath = PySdkSettings.instance.preferredVirtualEnvBaseSdk.takeIf(FileUtil::exists) - val detectedPreferredSdk = items.find { it.homePath == preferredSdkPath } - selectedSdk = when { - detectedPreferredSdk != null -> detectedPreferredSdk - preferredSdkPath != null -> PyDetectedSdk(preferredSdkPath).apply { - childComponent.insertItemAt(this, 0) + val preferredSdk = PyProjectVirtualEnvConfiguration.findPreferredVirtualEnvBaseSdk(items) + if (preferredSdk != null) { + if (items.find { it.homePath == preferredSdk.homePath } == null) { + childComponent.insertItemAt(preferredSdk, 0) } - else -> items.getOrNull(0) + selectedSdk = preferredSdk } } callback() diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyProjectVirtualEnvConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyProjectVirtualEnvConfiguration.kt new file mode 100644 index 000000000000..733f8c640701 --- /dev/null +++ b/python/src/com/jetbrains/python/sdk/configuration/PyProjectVirtualEnvConfiguration.kt @@ -0,0 +1,68 @@ +// Copyright 2000-2020 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.sdk.configuration + +import com.intellij.execution.ExecutionException +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleUtil +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.Task +import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.util.UserDataHolder +import com.intellij.openapi.util.UserDataHolderBase +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.util.concurrency.annotations.RequiresEdt +import com.jetbrains.python.PySdkBundle +import com.jetbrains.python.packaging.PyPackageManager +import com.jetbrains.python.sdk.* + +object PyProjectVirtualEnvConfiguration { + @RequiresEdt + fun createVirtualEnvSynchronously(baseSdk: Sdk?, + existingSdks: List, + venvRoot: String, + projectBasePath: String?, + project: Project?, + module: Module?, + context: UserDataHolder = UserDataHolderBase(), + inheritSitePackages: Boolean = false, + makeShared: Boolean = false): Sdk? { + val installedSdk = installSdkIfNeeded(baseSdk, module, existingSdks, context) + if (installedSdk == null) return null + + val projectPath = projectBasePath ?: module?.basePath ?: project?.basePath + val task = object : Task.WithResult(project, PySdkBundle.message("python.creating.venv.title"), false) { + override fun compute(indicator: ProgressIndicator): String { + indicator.isIndeterminate = true + val packageManager = PyPackageManager.getInstance(installedSdk) + return packageManager.createVirtualEnv(venvRoot, inheritSitePackages) + } + } + val associatedPath = if (!makeShared) projectPath else null + val venvSdk = createSdkByGenerateTask(task, existingSdks, installedSdk, associatedPath, null) ?: return null + if (!makeShared) { + venvSdk.associateWithModule(module, projectBasePath) + } + moduleToExcludeSdkFrom(venvRoot, project)?.excludeInnerVirtualEnv(venvSdk) + PySdkSettings.instance.onVirtualEnvCreated(installedSdk, FileUtil.toSystemIndependentName(venvRoot), projectPath) + return venvSdk + } + + fun findPreferredVirtualEnvBaseSdk(existingBaseSdks: List): Sdk? { + val preferredSdkPath = PySdkSettings.instance.preferredVirtualEnvBaseSdk.takeIf(FileUtil::exists) + val detectedPreferredSdk = existingBaseSdks.find { it.homePath == preferredSdkPath } + return when { + detectedPreferredSdk != null -> detectedPreferredSdk + preferredSdkPath != null -> PyDetectedSdk(preferredSdkPath) + else -> existingBaseSdks.getOrNull(0) + } + } + + private fun moduleToExcludeSdkFrom(path: String, project: Project?): Module? { + val possibleProjects = if (project != null) listOf(project) else ProjectManager.getInstance().openProjects.asList() + val rootFile = StandardFileSystems.local().refreshAndFindFileByPath(path) ?: return null + return possibleProjects.mapNotNull { ModuleUtil.findModuleForFile(rootFile, it) }.firstOrNull() + } +} \ No newline at end of file