(model: PythonMutableTargetAddInterpreterModel, errorSink: ErrorSink) : CustomNewEnvironmentCreator
("pipenv", model, errorSink) {
+internal class EnvironmentCreatorPip
(model: PythonMutableTargetAddInterpreterModel
, errorSink: ErrorSink) : CustomNewEnvironmentCreator
("pipenv", model, errorSink) {
override val interpreterType: InterpreterType = InterpreterType.PIPENV
override val executable: ObservableMutableProperty?> = model.state.pipenvExecutable
@@ -23,7 +23,7 @@ internal class EnvironmentCreatorPip(model: PythonMutableTargetAd
val savingPath = (pathHolder as? PathHolder.Eel)?.path
?: (executable.get()?.pathHolder as? PathHolder.Eel)?.path
savingPath?.let {
- PropertiesComponent.getInstance().pipEnvPath = it.toString()
+ PropertiesComponent.getInstance().pipenvPath = it.toString()
}
}
@@ -37,4 +37,4 @@ internal class EnvironmentCreatorPip(model: PythonMutableTargetAd
override suspend fun detectExecutable() {
model.detectPipEnvExecutable()
}
-}
\ No newline at end of file
+}
diff --git a/python/src/com/jetbrains/python/sdk/add/v2/models.kt b/python/src/com/jetbrains/python/sdk/add/v2/models.kt
index b188c133b127..02fca01b529d 100644
--- a/python/src/com/jetbrains/python/sdk/add/v2/models.kt
+++ b/python/src/com/jetbrains/python/sdk/add/v2/models.kt
@@ -13,7 +13,9 @@ import com.intellij.openapi.vfs.toNioPathOrNull
import com.intellij.platform.eel.provider.localEel
import com.intellij.python.community.execService.BinOnEel
import com.intellij.python.community.execService.BinaryToExec
-import com.intellij.python.community.services.shared.*
+import com.intellij.python.community.services.shared.LanguageLevelHolder
+import com.intellij.python.community.services.shared.LanguageLevelWithUiComparator
+import com.intellij.python.community.services.shared.UiHolder
import com.intellij.python.hatch.HatchConfiguration
import com.intellij.python.hatch.HatchVirtualEnvironment
import com.intellij.python.hatch.getHatchService
@@ -21,19 +23,19 @@ import com.intellij.python.pyproject.PyProjectToml
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.jetbrains.python.*
import com.jetbrains.python.PyBundle.message
-import com.jetbrains.python.PyToolUIInfo
-import com.jetbrains.python.Result
import com.jetbrains.python.Result.Companion.success
-import com.jetbrains.python.TraceContext
import com.jetbrains.python.errorProcessing.ErrorSink
import com.jetbrains.python.errorProcessing.PyResult
import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows
import com.jetbrains.python.psi.LanguageLevel
-import com.jetbrains.python.sdk.*
+import com.jetbrains.python.sdk.PySdkToInstall
+import com.jetbrains.python.sdk.PySdkUtil
import com.jetbrains.python.sdk.add.v2.conda.detectCondaEnvironments
import com.jetbrains.python.sdk.add.v2.conda.detectCondaExecutable
import com.jetbrains.python.sdk.add.v2.hatch.HatchUIError
+import com.jetbrains.python.sdk.basePath
import com.jetbrains.python.sdk.flavors.conda.PyCondaEnv
+import com.jetbrains.python.sdk.isSystemWide
import com.jetbrains.python.sdk.pipenv.getPipEnvExecutable
import com.jetbrains.python.sdk.poetry.getPoetryExecutable
import com.jetbrains.python.sdk.uv.impl.getUvExecutable
diff --git a/python/src/com/jetbrains/python/sdk/conda/PyCondaSdkCustomizer.kt b/python/src/com/jetbrains/python/sdk/conda/PyCondaSdkCustomizer.kt
index 5f3392ac4ba1..a23d560d79ff 100644
--- a/python/src/com/jetbrains/python/sdk/conda/PyCondaSdkCustomizer.kt
+++ b/python/src/com/jetbrains/python/sdk/conda/PyCondaSdkCustomizer.kt
@@ -1,11 +1,11 @@
// 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.conda
-import com.intellij.codeInspection.util.IntentionName
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
+import com.jetbrains.python.sdk.configuration.CreateSdkInfo
import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension
import org.jetbrains.annotations.ApiStatus
@@ -35,11 +35,9 @@ interface PyCondaSdkCustomizer {
get() = EP_NAME.extensionList.first()
@RequiresBackgroundThread
- @IntentionName
- @Suppress("HardCodedStringLiteral")
- fun getIntentionBlocking(extension: PyProjectSdkConfigurationExtension, module: Module): String? =
+ fun checkEnvironmentAndPrepareSdkCreatorBlocking(extension: PyProjectSdkConfigurationExtension, module: Module): CreateSdkInfo? =
runBlockingMaybeCancellable {
- extension.getIntention(module)
+ extension.checkEnvironmentAndPrepareSdkCreator(module)
}
}
}
diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt
index 9a5af691844a..bb4ef59af1a4 100644
--- a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt
+++ b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt
@@ -17,50 +17,43 @@ import com.intellij.openapi.util.use
import com.intellij.openapi.wm.ex.WelcomeScreenProjectProvider
import com.intellij.platform.ide.progress.withBackgroundProgress
import com.jetbrains.python.PyBundle
-import com.jetbrains.python.sdk.impl.PySdkBundle
import com.jetbrains.python.PythonPluginDisposable
-import com.jetbrains.python.errorProcessing.PyResult
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
import com.jetbrains.python.sdk.PySdkPopupFactory
import com.jetbrains.python.sdk.configuration.suppressors.PyInterpreterInspectionSuppressor
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.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
object PyProjectSdkConfiguration {
- fun configureSdkUsingExtension(module: Module, extension: PyProjectSdkConfigurationExtension) {
- val lifetime = suppressTipAndInspectionsFor(module, extension)
+ fun configureSdkUsingCreateSdkInfo(module: Module, createSdkInfo: CreateSdkInfo) {
+ val lifetime = suppressTipAndInspectionsFor(module, createSdkInfo.toolInfo.toolName)
val project = module.project
PyPackageCoroutine.launch(project) {
- val title = extension.getIntention(module) ?: PySdkBundle.message("python.configuring.interpreter.progress")
- withBackgroundProgress(project, title, false) {
- lifetime.use {
- setSdkUsingExtension(module, extension) {
- withContext(Dispatchers.Default) {
- extension.createAndAddSdkForInspection(module)
- }
- }
- }
+ withBackgroundProgress(project, createSdkInfo.intentionName, false) {
+ lifetime.use { setSdkUsingCreateSdkInfo(module, createSdkInfo, false) }
}
}
}
- suspend fun setSdkUsingExtension(module: Module, extension: PyProjectSdkConfigurationExtension, supplier: suspend () -> PyResult): Boolean {
- thisLogger().debug("Configuring sdk with ${extension.javaClass.canonicalName} extension")
+ suspend fun setSdkUsingCreateSdkInfo(
+ module: Module, createSdkInfo: CreateSdkInfo, needsConfirmation: NeedsConfirmation,
+ ): Boolean = withContext(Dispatchers.Default) {
+ thisLogger().debug("Configuring sdk using ${createSdkInfo.toolInfo.toolName}")
- val sdk = supplier().getOr {
+ val sdk = createSdkInfo.sdkCreator(needsConfirmation).getOr {
ShowingMessageErrorSync.emit(it.error)
- return true
- } ?: return false
+ return@withContext true
+ } ?: return@withContext false
- // TODO Move this to PyUvSdkConfiguration, show better notification
setReadyToUseSdk(module.project, module, sdk)
- return true
+ true
}
fun setReadyToUseSdkSync(project: Project, module: Module, sdk: Sdk) {
@@ -80,12 +73,12 @@ object PyProjectSdkConfiguration {
}
}
- fun suppressTipAndInspectionsFor(module: Module, extension: PyProjectSdkConfigurationExtension): Disposable {
+ fun suppressTipAndInspectionsFor(module: Module, toolName: String): Disposable {
val project = module.project
val lifetime = Disposer.newDisposable(
PythonPluginDisposable.getInstance(project),
- "Configuring sdk using ${extension.javaClass.name} extension"
+ "Configuring sdk using $toolName"
)
TipOfTheDaySuppressor.suppress()?.let { Disposer.register(lifetime, it) }
diff --git a/python/src/com/jetbrains/python/sdk/flavors/conda/NewCondaEnvRequest.kt b/python/src/com/jetbrains/python/sdk/flavors/conda/NewCondaEnvRequest.kt
index 2ec19c07b406..990386faf15e 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/conda/NewCondaEnvRequest.kt
+++ b/python/src/com/jetbrains/python/sdk/flavors/conda/NewCondaEnvRequest.kt
@@ -1,7 +1,6 @@
// 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.flavors.conda
-import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.python.community.execService.BinaryToExec
import com.jetbrains.python.errorProcessing.PyResult
@@ -72,9 +71,9 @@ sealed class NewCondaEnvRequest {
}
}
- private fun readEnvName(): String = runReadAction {
- val virtualFile = VirtualFileManager.getInstance().findFileByNioPath(environmentYaml) ?: return@runReadAction DEFAULT_ENV_NAME
- CondaEnvironmentYmlParser.readNameFromFile(virtualFile) ?: DEFAULT_ENV_NAME
+ private fun readEnvName(): String {
+ val virtualFile = VirtualFileManager.getInstance().findFileByNioPath(environmentYaml) ?: return DEFAULT_ENV_NAME
+ return CondaEnvironmentYmlParser.readNameFromFile(virtualFile) ?: DEFAULT_ENV_NAME
}
}
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt
index 8091da7b9686..17614e854472 100644
--- a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt
+++ b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt
@@ -15,7 +15,6 @@ import org.jetbrains.annotations.ApiStatus.Internal
object PipEnvFileHelper {
const val PIP_FILE: String = "Pipfile"
const val PIP_FILE_LOCK: String = "Pipfile.lock"
- const val PIPENV_PATH_SETTING: String = "PyCharm.Pipenv.Path"
fun getPipFileLock(sdk: Sdk): VirtualFile? =
sdk.associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) }
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
index 774d67e1a4e9..a38644370962 100644
--- a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
+++ b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.platform.eel.provider.localEel
import com.intellij.platform.eel.where
+import com.intellij.python.community.impl.pipenv.pipenvPath
import com.jetbrains.python.PyBundle
import com.jetbrains.python.PythonBinary
import com.jetbrains.python.errorProcessing.PyResult
@@ -30,15 +31,6 @@ suspend fun runPipEnv(dirPath: Path?, vararg args: String): PyResult {
return runExecutableWithProgress(executable, dirPath, 10.minutes, args = args)
}
-/**
- * The user-set persisted a path to the pipenv executable.
- */
-var PropertiesComponent.pipEnvPath: @SystemDependent String?
- get() = getValue(PipEnvFileHelper.PIPENV_PATH_SETTING)
- set(value) {
- setValue(PipEnvFileHelper.PIPENV_PATH_SETTING, value)
- }
-
/**
* Detects the pipenv executable in `$PATH`.
*/
@@ -66,7 +58,7 @@ fun detectPipEnvExecutableOrNull(): Path? {
*/
@Internal
suspend fun getPipEnvExecutable(): PyResult =
- PropertiesComponent.getInstance().pipEnvPath?.let { PyResult.success(Path.of(it)) } ?: detectPipEnvExecutable()
+ PropertiesComponent.getInstance().pipenvPath?.let { PyResult.success(Path.of(it)) } ?: detectPipEnvExecutable()
/**
* Sets up the pipenv environment under the modal progress window.