diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml index 9ea8e99f276f..cb2441d7d0f4 100644 --- a/python/pluginResources/intellij.python.community.impl.xml +++ b/python/pluginResources/intellij.python.community.impl.xml @@ -965,20 +965,20 @@ - - "/> - - - diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties index 13efe4b56d12..33b0d40d4a11 100644 --- a/python/pluginResources/messages/PyBundle.properties +++ b/python/pluginResources/messages/PyBundle.properties @@ -1810,5 +1810,6 @@ sdk.progress.text.setting.up.poetry.environment=Setting up Poetry environment sdk.create.venv.suggestion=Create a virtual environment using {0} sdk.use.existing.venv=Use existing virtual environment {0} sdk.create.venv.suggestion.no.arg=Create a virtual environment +sdk.cannot.find.venv.for.module=Can't find venv for the module sdk.set.up.uv.environment=Set up a uv {0} environment diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt b/python/src/com/jetbrains/python/conda/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt similarity index 97% rename from python/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt rename to python/src/com/jetbrains/python/conda/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt index 15ca09abbcc5..970b1ba74b21 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/conda/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt @@ -1,5 +1,5 @@ // Copyright 2000-2026 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 +package com.jetbrains.python.conda.sdk.configuration import com.intellij.openapi.application.EDT import com.intellij.openapi.diagnostic.thisLogger @@ -35,6 +35,7 @@ import com.jetbrains.python.sdk.conda.createCondaSdkAlongWithNewEnv import com.jetbrains.python.sdk.conda.createCondaSdkFromExistingEnv import com.jetbrains.python.sdk.conda.execution.CondaExecutor import com.jetbrains.python.sdk.conda.suggestCondaPath +import com.jetbrains.python.sdk.configuration.* import com.jetbrains.python.sdk.configuration.PySdkConfigurationCollector.CondaEnvResult import com.jetbrains.python.sdk.findAmongRoots import com.jetbrains.python.sdk.flavors.conda.NewCondaEnvRequest @@ -59,9 +60,10 @@ internal class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExten override val toolId: ToolId = CONDA_TOOL_ID - override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = prepareSdkCreator( - { checkManageableEnv(module) } - ) { envExists -> { createAndAddSdk(module, envExists) } } + override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module) } + ) { envExists -> { createAndAddSdk(module, envExists) } } override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension? = null diff --git a/python/src/com/jetbrains/python/hatch/sdk/configuration/PyHatchSdkConfiguration.kt b/python/src/com/jetbrains/python/hatch/sdk/configuration/PyHatchSdkConfiguration.kt new file mode 100644 index 000000000000..e24f26ff558e --- /dev/null +++ b/python/src/com/jetbrains/python/hatch/sdk/configuration/PyHatchSdkConfiguration.kt @@ -0,0 +1,96 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.python.hatch.sdk.configuration + +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.platform.util.progress.reportRawProgress +import com.intellij.python.common.tools.ToolId +import com.intellij.python.hatch.HatchVirtualEnvironment +import com.intellij.python.hatch.PythonVirtualEnvironment +import com.intellij.python.hatch.cli.HatchEnvironment +import com.intellij.python.hatch.getHatchService +import com.intellij.python.hatch.impl.HATCH_TOOL_ID +import com.jetbrains.python.PyBundle +import com.jetbrains.python.PythonBinary +import com.jetbrains.python.errorProcessing.PyResult +import com.jetbrains.python.hatch.sdk.createSdk +import com.jetbrains.python.onSuccess +import com.jetbrains.python.orLogException +import com.jetbrains.python.sdk.configuration.* +import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService +import com.jetbrains.python.sdk.setAssociationToModule +import com.jetbrains.python.util.runWithModalBlockingOrInBackground + +internal class PyHatchSdkConfiguration : PyProjectTomlConfigurationExtension { + companion object { + private val LOGGER = Logger.getInstance(PyHatchSdkConfiguration::class.java) + } + + override val toolId: ToolId = HATCH_TOOL_ID + + override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module, true) }, + ) { envExists -> { createSdk(module, envExists) } } + + override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module, false) }, + ) { envExists -> { createSdk(module, envExists) } } + + override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this + + private suspend fun checkManageableEnv( + module: Module, checkToml: CheckToml, + ): EnvCheckerResult = reportRawProgress { + it.text(PyBundle.message("sdk.set.up.hatch.project.analysis")) + val hatchService = module.getHatchService().getOr { return EnvCheckerResult.CannotConfigure } + val canManage = if (checkToml) hatchService.isHatchManagedProject() else true + val intentionName = PyBundle.message("sdk.set.up.hatch.environment") + val envNotFound = EnvCheckerResult.EnvNotFound(intentionName) + + if (canManage) { + val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull().orLogException(LOGGER)?.pythonVirtualEnvironment + when (defaultEnv) { + is PythonVirtualEnvironment.Existing -> EnvCheckerResult.EnvFound(defaultEnv.pythonInfo, intentionName) + is PythonVirtualEnvironment.NotExisting, null -> envNotFound + } + } else EnvCheckerResult.CannotConfigure + } + + /** + * Creates SDK for Hatch, it will also create a new Hatch environment and use an existing one. + * + * @param module module used to create SDK + * @param envExists shows whether the environment already exists or a new one should be created + */ + private fun createSdk(module: Module, envExists: EnvExists): PyResult = runWithModalBlockingOrInBackground( + project = module.project, + msg = PyBundle.message("sdk.set.up.hatch.environment") + ) { + val hatchService = module.getHatchService().getOr { return@runWithModalBlockingOrInBackground it } + + val environment = if (envExists) { + val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull() + .mapSuccess { it?.pythonVirtualEnvironment } + .getOr { return@runWithModalBlockingOrInBackground it } + when (defaultEnv) { + is PythonVirtualEnvironment.Existing -> defaultEnv + is PythonVirtualEnvironment.NotExisting, null -> return@runWithModalBlockingOrInBackground PyResult.localizedError( + PyBundle.message("sdk.could.not.find.valid.hatch.environment") + ) + } + } else { + hatchService.createVirtualEnvironment().getOr { return@runWithModalBlockingOrInBackground it } + } + + val hatchVenv = HatchVirtualEnvironment(HatchEnvironment.Companion.DEFAULT, environment) + val sdk = hatchVenv.createSdk(hatchService.getWorkingDirectoryPath()).onSuccess { sdk -> + sdk.setAssociationToModule(module) + module.project.pySdkService.persistSdk(sdk) + } + sdk + } + +} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt b/python/src/com/jetbrains/python/pipenv/sdk/configuration/PyPipfileSdkConfiguration.kt similarity index 98% rename from python/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt rename to python/src/com/jetbrains/python/pipenv/sdk/configuration/PyPipfileSdkConfiguration.kt index da7c492905b2..21506ac74b27 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/pipenv/sdk/configuration/PyPipfileSdkConfiguration.kt @@ -1,5 +1,5 @@ // Copyright 2000-2026 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 +package com.jetbrains.python.pipenv.sdk.configuration import com.intellij.ide.util.PropertiesComponent import com.intellij.openapi.application.EDT @@ -18,6 +18,7 @@ import com.jetbrains.python.PythonBinary import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.sdk.PythonSdkType import com.jetbrains.python.sdk.baseDir +import com.jetbrains.python.sdk.configuration.* import com.jetbrains.python.sdk.configuration.PySdkConfigurationCollector.PipEnvResult import com.jetbrains.python.sdk.findAmongRoots import com.jetbrains.python.sdk.impl.PySdkBundle diff --git a/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt b/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt new file mode 100644 index 000000000000..5230cef8de3a --- /dev/null +++ b/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt @@ -0,0 +1,120 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.python.poetry.sdk.configuration + +import com.intellij.openapi.application.EDT +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil +import com.intellij.openapi.util.io.toNioPathOrNull +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.platform.ide.progress.withBackgroundProgress +import com.intellij.platform.util.progress.reportRawProgress +import com.intellij.python.common.tools.ToolId +import com.intellij.python.community.impl.poetry.common.POETRY_TOOL_ID +import com.intellij.python.pyproject.PyProjectToml +import com.jetbrains.python.PyBundle +import com.jetbrains.python.PythonBinary +import com.jetbrains.python.errorProcessing.PyResult +import com.jetbrains.python.poetry.findPoetryLock +import com.jetbrains.python.poetry.getPyProjectTomlForPoetry +import com.jetbrains.python.sdk.PythonSdkType +import com.jetbrains.python.sdk.baseDir +import com.jetbrains.python.sdk.configuration.* +import com.jetbrains.python.sdk.impl.PySdkBundle +import com.jetbrains.python.sdk.impl.resolvePythonBinary +import com.jetbrains.python.sdk.legacy.PythonSdkUtil +import com.jetbrains.python.sdk.poetry.* +import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService +import com.jetbrains.python.sdk.setAssociationToModule +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.nio.file.Path +import kotlin.io.path.pathString + +internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension { + + companion object { + private val LOGGER = Logger.getInstance(PyPoetrySdkConfiguration::class.java) + } + + override val toolId: ToolId = POETRY_TOOL_ID + + override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module, true) }, + ) { { createPoetry(module) } } + + override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module, false) }, + ) { { createPoetry(module) } } + + override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this + + private suspend fun checkManageableEnv( + module: Module, checkToml: CheckToml, + ): EnvCheckerResult = reportRawProgress { + it.text(PyBundle.message("python.sdk.validating.environment")) + + val isPoetryProject = if (checkToml) { + withContext(Dispatchers.IO) { + PyProjectToml.Companion.findFile(module) + ?.let { toml -> getPyProjectTomlForPoetry(toml) } != null || findPoetryLock(module) != null + } + } else true + + val canManage = isPoetryProject && getPoetryExecutable() != null + val intentionName = PyBundle.message("sdk.set.up.poetry.environment") + val envNotFound = EnvCheckerResult.EnvNotFound(intentionName) + + if (canManage) { + val basePath = module.baseDir?.path?.toNioPathOrNull() + runPoetry(basePath, "check", "--lock").getOr { return@reportRawProgress envNotFound } + val envPath = runPoetry(basePath, "env", "info", "-p") + .mapSuccess { it.toNioPathOrNull() } + .getOr { return@reportRawProgress envNotFound } + envPath?.resolvePythonBinary()?.findEnvOrNull(intentionName) ?: envNotFound + } else EnvCheckerResult.CannotConfigure + } + + private suspend fun createPoetry(module: Module): PyResult = + withBackgroundProgress(module.project, PyBundle.message("sdk.progress.text.setting.up.poetry.environment")) { + LOGGER.debug("Creating poetry environment") + + val basePath = module.baseDir?.path?.let { Path.of(it) } + if (basePath == null) { + return@withBackgroundProgress PyResult.localizedError( + PyBundle.message( + "python.sdk.provided.path.is.invalid", + module.baseDir?.path + ) + ) + } + val tomlFile = PyProjectToml.Companion.findFile(module) + val poetry = setupPoetry(basePath, null, true, tomlFile == null).getOr { return@withBackgroundProgress it } + val path = poetry.resolvePythonBinary() + ?: return@withBackgroundProgress PyResult.localizedError(PySdkBundle.message("cannot.find.executable", "python", poetry)) + + val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path.pathString) + ?: return@withBackgroundProgress PyResult.localizedError(PySdkBundle.message("cannot.find.executable", "python", path)) + + LOGGER.debug("Setting up associated poetry environment: $path, $basePath") + val sdk = SdkConfigurationUtil.setupSdk( + PythonSdkUtil.getAllSdks().toTypedArray(), + file, + PythonSdkType.getInstance(), + PyPoetrySdkAdditionalData(module.baseDir?.path?.let { Path.of(it) }), + suggestedSdkName(basePath) + ) + + withContext(Dispatchers.EDT) { + LOGGER.debug("Adding associated poetry environment: $path, $basePath") + sdk.setAssociationToModule(module) + SdkConfigurationUtil.addSdk(sdk) + module.project.pySdkService.persistSdk(sdk) + } + + PyResult.success(sdk) + } +} diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyHatchSdkConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyHatchSdkConfiguration.kt deleted file mode 100644 index 32841deb15ae..000000000000 --- a/python/src/com/jetbrains/python/sdk/configuration/PyHatchSdkConfiguration.kt +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2000-2026 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.openapi.diagnostic.Logger -import com.intellij.openapi.module.Module -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.platform.util.progress.reportRawProgress -import com.intellij.python.common.tools.ToolId -import com.intellij.python.hatch.HatchVirtualEnvironment -import com.intellij.python.hatch.PythonVirtualEnvironment -import com.intellij.python.hatch.cli.HatchEnvironment -import com.intellij.python.hatch.getHatchService -import com.intellij.python.hatch.impl.HATCH_TOOL_ID -import com.jetbrains.python.PyBundle -import com.jetbrains.python.PythonBinary -import com.jetbrains.python.errorProcessing.PyResult -import com.jetbrains.python.hatch.sdk.createSdk -import com.jetbrains.python.onSuccess -import com.jetbrains.python.orLogException -import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService -import com.jetbrains.python.sdk.setAssociationToModule -import com.jetbrains.python.util.runWithModalBlockingOrInBackground - -internal class PyHatchSdkConfiguration : PyProjectTomlConfigurationExtension { - companion object { - private val LOGGER = Logger.getInstance(PyHatchSdkConfiguration::class.java) - } - - override val toolId: ToolId = HATCH_TOOL_ID - - override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = - prepareSdkCreator( - { checkManageableEnv(module, true) }, - ) { envExists -> { createSdk(module, envExists) } } - - override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List): CreateSdkInfo? = - prepareSdkCreator( - { checkManageableEnv(module, false) }, - ) { envExists -> { createSdk(module, envExists) } } - - override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this - - private suspend fun checkManageableEnv( - module: Module, checkToml: CheckToml, - ): EnvCheckerResult = reportRawProgress { - it.text(PyBundle.message("sdk.set.up.hatch.project.analysis")) - val hatchService = module.getHatchService().getOr { return EnvCheckerResult.CannotConfigure } - val canManage = if (checkToml) hatchService.isHatchManagedProject() else true - val intentionName = PyBundle.message("sdk.set.up.hatch.environment") - val envNotFound = EnvCheckerResult.EnvNotFound(intentionName) - - if (canManage) { - val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull().orLogException(LOGGER)?.pythonVirtualEnvironment - when (defaultEnv) { - is PythonVirtualEnvironment.Existing -> EnvCheckerResult.EnvFound(defaultEnv.pythonInfo, intentionName) - is PythonVirtualEnvironment.NotExisting, null -> envNotFound - } - } - else EnvCheckerResult.CannotConfigure - } - - /** - * Creates SDK for Hatch, it will also create a new Hatch environment and use an existing one. - * - * @param module module used to create SDK - * @param envExists shows whether the environment already exists or a new one should be created - */ - private fun createSdk(module: Module, envExists: EnvExists): PyResult = runWithModalBlockingOrInBackground( - project = module.project, - msg = PyBundle.message("sdk.set.up.hatch.environment") - ) { - val hatchService = module.getHatchService().getOr { return@runWithModalBlockingOrInBackground it } - - val environment = if (envExists) { - val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull() - .mapSuccess { it?.pythonVirtualEnvironment } - .getOr { return@runWithModalBlockingOrInBackground it } - when (defaultEnv) { - is PythonVirtualEnvironment.Existing -> defaultEnv - is PythonVirtualEnvironment.NotExisting, null -> return@runWithModalBlockingOrInBackground PyResult.localizedError( - PyBundle.message("sdk.could.not.find.valid.hatch.environment")) - } - } - else { - hatchService.createVirtualEnvironment().getOr { return@runWithModalBlockingOrInBackground it } - } - - val hatchVenv = HatchVirtualEnvironment(HatchEnvironment.DEFAULT, environment) - val sdk = hatchVenv.createSdk(hatchService.getWorkingDirectoryPath()).onSuccess { sdk -> - sdk.setAssociationToModule(module) - module.project.pySdkService.persistSdk(sdk) - } - sdk - } - -} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyPoetrySdkConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyPoetrySdkConfiguration.kt deleted file mode 100644 index 1805c147e1eb..000000000000 --- a/python/src/com/jetbrains/python/sdk/configuration/PyPoetrySdkConfiguration.kt +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2000-2026 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.openapi.application.EDT -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.module.Module -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil -import com.intellij.openapi.util.io.toNioPathOrNull -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.platform.ide.progress.withBackgroundProgress -import com.intellij.platform.util.progress.reportRawProgress -import com.intellij.python.common.tools.ToolId -import com.intellij.python.community.impl.poetry.common.POETRY_TOOL_ID -import com.intellij.python.pyproject.PyProjectToml -import com.jetbrains.python.PyBundle -import com.jetbrains.python.PythonBinary -import com.jetbrains.python.errorProcessing.PyResult -import com.jetbrains.python.poetry.findPoetryLock -import com.jetbrains.python.poetry.getPyProjectTomlForPoetry -import com.jetbrains.python.sdk.PythonSdkType -import com.jetbrains.python.sdk.baseDir -import com.jetbrains.python.sdk.impl.PySdkBundle -import com.jetbrains.python.sdk.impl.resolvePythonBinary -import com.jetbrains.python.sdk.legacy.PythonSdkUtil -import com.jetbrains.python.sdk.poetry.* -import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService -import com.jetbrains.python.sdk.setAssociationToModule -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.nio.file.Path -import kotlin.io.path.pathString - -internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension { - - companion object { - private val LOGGER = Logger.getInstance(PyPoetrySdkConfiguration::class.java) - } - - override val toolId: ToolId = POETRY_TOOL_ID - - override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = - prepareSdkCreator( - { checkManageableEnv(module, true) }, - ) { { createPoetry(module) } } - - override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List): CreateSdkInfo? = - prepareSdkCreator( - { checkManageableEnv(module, false) }, - ) { { createPoetry(module) } } - - override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this - - private suspend fun checkManageableEnv( - module: Module, checkToml: CheckToml, - ): EnvCheckerResult = reportRawProgress { - it.text(PyBundle.message("python.sdk.validating.environment")) - - val isPoetryProject = if (checkToml) { - withContext(Dispatchers.IO) { - PyProjectToml.findFile(module)?.let { toml -> getPyProjectTomlForPoetry(toml) } != null || findPoetryLock(module) != null - } - } - else true - - val canManage = isPoetryProject && getPoetryExecutable() != null - val intentionName = PyBundle.message("sdk.set.up.poetry.environment") - val envNotFound = EnvCheckerResult.EnvNotFound(intentionName) - - if (canManage) { - val basePath = module.baseDir?.path?.toNioPathOrNull() - runPoetry(basePath, "check", "--lock").getOr { return@reportRawProgress envNotFound } - val envPath = runPoetry(basePath, "env", "info", "-p") - .mapSuccess { it.toNioPathOrNull() } - .getOr { return@reportRawProgress envNotFound } - envPath?.resolvePythonBinary()?.findEnvOrNull(intentionName) ?: envNotFound - } - else EnvCheckerResult.CannotConfigure - } - - private suspend fun createPoetry(module: Module): PyResult = - withBackgroundProgress(module.project, PyBundle.message("sdk.progress.text.setting.up.poetry.environment")) { - LOGGER.debug("Creating poetry environment") - - val basePath = module.baseDir?.path?.let { Path.of(it) } - if (basePath == null) { - return@withBackgroundProgress PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", module.baseDir?.path)) - } - val tomlFile = PyProjectToml.findFile(module) - val poetry = setupPoetry(basePath, null, true, tomlFile == null).getOr { return@withBackgroundProgress it } - val path = poetry.resolvePythonBinary() - ?: return@withBackgroundProgress PyResult.localizedError(PySdkBundle.message("cannot.find.executable", "python", poetry)) - - val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path.pathString) - ?: return@withBackgroundProgress PyResult.localizedError(PySdkBundle.message("cannot.find.executable", "python", path)) - - LOGGER.debug("Setting up associated poetry environment: $path, $basePath") - val sdk = SdkConfigurationUtil.setupSdk( - PythonSdkUtil.getAllSdks().toTypedArray(), - file, - PythonSdkType.getInstance(), - PyPoetrySdkAdditionalData(module.baseDir?.path?.let { Path.of(it) }), - suggestedSdkName(basePath) - ) - - withContext(Dispatchers.EDT) { - LOGGER.debug("Adding associated poetry environment: $path, $basePath") - sdk.setAssociationToModule(module) - SdkConfigurationUtil.addSdk(sdk) - module.project.pySdkService.persistSdk(sdk) - } - - PyResult.success(sdk) - } -} diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyUvSdkConfiguration.kt b/python/src/com/jetbrains/python/uv/sdk/configuration/PyUvSdkConfiguration.kt similarity index 92% rename from python/src/com/jetbrains/python/sdk/configuration/PyUvSdkConfiguration.kt rename to python/src/com/jetbrains/python/uv/sdk/configuration/PyUvSdkConfiguration.kt index 2c7f978184f5..427aad8fe226 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyUvSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/uv/sdk/configuration/PyUvSdkConfiguration.kt @@ -1,5 +1,5 @@ // Copyright 2000-2026 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 +package com.jetbrains.python.uv.sdk.configuration import com.intellij.openapi.application.EDT import com.intellij.openapi.diagnostic.fileLogger @@ -14,6 +14,11 @@ import com.jetbrains.python.PythonBinary import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.onSuccess import com.jetbrains.python.sdk.baseDir +import com.jetbrains.python.sdk.configuration.CreateSdkInfo +import com.jetbrains.python.sdk.configuration.EnvCheckerResult +import com.jetbrains.python.sdk.configuration.PyProjectTomlConfigurationExtension +import com.jetbrains.python.sdk.configuration.findEnvOrNull +import com.jetbrains.python.sdk.configuration.prepareSdkCreator import com.jetbrains.python.sdk.persist import com.jetbrains.python.sdk.pyvenvContains import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt b/python/src/com/jetbrains/python/venv/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt similarity index 93% rename from python/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt rename to python/src/com/jetbrains/python/venv/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt index 46fc908b3fed..57b58002f617 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt +++ b/python/src/com/jetbrains/python/venv/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt @@ -1,5 +1,5 @@ // Copyright 2000-2026 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 +package com.jetbrains.python.venv.sdk.configuration import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.module.Module @@ -15,15 +15,17 @@ import com.jetbrains.python.packaging.requirementsTxt.PythonRequirementTxtSdkUti import com.jetbrains.python.packaging.setupPy.SetupPyManager import com.jetbrains.python.projectCreation.createVenvAndSdk import com.jetbrains.python.sdk.ModuleOrProject +import com.jetbrains.python.sdk.configuration.* import com.jetbrains.python.sdk.configuration.PySdkConfigurationCollector.VirtualEnvResult internal class PyRequirementsTxtOrSetupPySdkConfiguration : PyProjectSdkConfigurationExtension { override val toolId: ToolId = PY_REQ_TOOL_ID // This is nonsense, but will be dropped soon - override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = prepareSdkCreator( - { checkManageableEnv(module) }, - ) { { createAndAddSdk(module) } } + override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List): CreateSdkInfo? = + prepareSdkCreator( + { checkManageableEnv(module) }, + ) { { createAndAddSdk(module) } } override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension? = null diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyVenvSdkConfiguration.kt b/python/src/com/jetbrains/python/venv/sdk/configuration/PyVenvSdkConfiguration.kt similarity index 94% rename from python/src/com/jetbrains/python/sdk/configuration/PyVenvSdkConfiguration.kt rename to python/src/com/jetbrains/python/venv/sdk/configuration/PyVenvSdkConfiguration.kt index 281fd897ce54..051e504ca74c 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyVenvSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/venv/sdk/configuration/PyVenvSdkConfiguration.kt @@ -1,5 +1,5 @@ // Copyright 2000-2026 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 +package com.jetbrains.python.venv.sdk.configuration import com.intellij.openapi.module.Module import com.intellij.openapi.projectRoots.Sdk @@ -12,6 +12,7 @@ import com.jetbrains.python.errorProcessing.MessageError import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.projectCreation.createVenvAndSdk import com.jetbrains.python.sdk.* +import com.jetbrains.python.sdk.configuration.* import com.jetbrains.python.sdk.flavors.PyFlavorAndData import com.jetbrains.python.sdk.flavors.PyFlavorData import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor @@ -58,7 +59,7 @@ internal class PyVenvSdkConfiguration : PyProjectSdkConfigurationExtension { private suspend fun setupExistingVenv(module: Module, venvsInModule: List): PyResult { val pythonBinary = withContext(Dispatchers.IO) { getVirtualEnv(venvsInModule)?.refreshAndFindVirtualFile() - } ?: return PyResult.failure(MessageError("Can't find venv for the module")) + } ?: return PyResult.failure(MessageError(PyBundle.message("sdk.cannot.find.venv.for.module"))) val pyDetectedSdk = PyDetectedSdk(pythonBinary.toString()) val sdk = pyDetectedSdk.setupAssociated(