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(