diff --git a/python/ide/impl/resources/intellij.pycharm.community.ide.impl.xml b/python/ide/impl/resources/intellij.pycharm.community.ide.impl.xml index cb9b9d8e4e3c..05b0e4c23ba4 100644 --- a/python/ide/impl/resources/intellij.pycharm.community.ide.impl.xml +++ b/python/ide/impl/resources/intellij.pycharm.community.ide.impl.xml @@ -104,7 +104,10 @@ id="environmentYml"/> - + + diff --git a/python/ide/impl/resources/messages/PyCharmCommunityCustomizationBundle.properties b/python/ide/impl/resources/messages/PyCharmCommunityCustomizationBundle.properties index b21c733b5fe5..a3a5b64eca76 100644 --- a/python/ide/impl/resources/messages/PyCharmCommunityCustomizationBundle.properties +++ b/python/ide/impl/resources/messages/PyCharmCommunityCustomizationBundle.properties @@ -58,6 +58,8 @@ sdk.dialog.title.setting.up.poetry.environment=Setting Up Poetry Environment sdk.notification.label.set.up.poetry.environment.from.pyproject.toml.dependencies=File pyproject.toml contains project dependencies. Would you like to set up a poetry environment? notification.group.pro.advertiser=PyCharm Professional recommended +sdk.set.up.uv.environment=Set up an uv environment using {0} + new.project.python.group.name=Python new.project.other.group.name=Other diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt index a79fb209cea6..cc9e2187625f 100644 --- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt @@ -34,20 +34,29 @@ import javax.swing.JComponent import javax.swing.JPanel import kotlin.io.path.pathString -/** - * This source code is created by @koxudaxi Koudai Aono - */ - class PyPoetrySdkConfiguration : PyProjectSdkConfigurationExtension { companion object { private val LOGGER = Logger.getInstance(PyPoetrySdkConfiguration::class.java) } - @RequiresBackgroundThread - override fun createAndAddSdkForConfigurator(module: Module): Sdk? = runBlockingCancellable { createAndAddSDk(module, false) } + override fun getIntention(module: Module): @IntentionName String? { + return runBlockingCancellable { + val toml = findAmongRoots(module, PY_PROJECT_TOML) + if (toml == null) { + return@runBlockingCancellable null + } + + val isPoetry = getPyProjectTomlForPoetry(toml) != null + if (!isPoetry) { + return@runBlockingCancellable null + } + + PyCharmCommunityCustomizationBundle.message("sdk.set.up.poetry.environment", toml.name) + } + } @RequiresBackgroundThread - override fun getIntention(module: Module): @IntentionName String? = findAmongRoots(module, PY_PROJECT_TOML)?.let { PyCharmCommunityCustomizationBundle.message("sdk.set.up.poetry.environment", it.name) } + override fun createAndAddSdkForConfigurator(module: Module): Sdk? = runBlockingCancellable { createAndAddSDk(module, false) } @RequiresBackgroundThread override fun createAndAddSdkForInspection(module: Module): Sdk? = runBlockingCancellable { createAndAddSDk(module, true) } diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyUvSdkConfiguration.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyUvSdkConfiguration.kt new file mode 100644 index 000000000000..83dc69a1a691 --- /dev/null +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyUvSdkConfiguration.kt @@ -0,0 +1,69 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.pycharm.community.ide.impl.configuration + +import com.intellij.codeInspection.util.IntentionName +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.module.Module +import com.intellij.openapi.progress.runBlockingCancellable +import com.intellij.openapi.projectRoots.ProjectJdkTable +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil +import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBundle +import com.intellij.util.concurrency.annotations.RequiresBackgroundThread +import com.jetbrains.python.sdk.* +import com.jetbrains.python.sdk.basePath +import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension +import com.jetbrains.python.sdk.uv.PY_PROJECT_TOML +import com.jetbrains.python.sdk.uv.getUvExecutable +import com.jetbrains.python.sdk.uv.setupUvSdkUnderProgress +import java.io.FileNotFoundException +import java.nio.file.Path + +class PyUvSdkConfiguration : PyProjectSdkConfigurationExtension { + companion object { + private val LOGGER = Logger.getInstance(PyUvSdkConfiguration::class.java) + } + + @RequiresBackgroundThread + override fun getIntention(module: Module): @IntentionName String? { + return findAmongRoots(module, PY_PROJECT_TOML)?.let { toml -> + getUvExecutable()?.let { PyCharmCommunityCustomizationBundle.message("sdk.set.up.uv.environment", toml.name) } + } + } + + @RequiresBackgroundThread + override fun createAndAddSdkForConfigurator(module: Module): Sdk? { + return runBlockingCancellable { + createUv(module).getOrElse { + LOGGER.warn(it) + null + } + } + } + + @RequiresBackgroundThread + override fun createAndAddSdkForInspection(module: Module): Sdk? { + return runBlockingCancellable { + createUv(module).getOrElse { + LOGGER.warn(it) + null + } + } + } + + override fun supportsHeadlessModel(): Boolean = true + + private suspend fun createUv(module: Module): Result { + val basePath = module.basePath?.let { Path.of(it) } + if (basePath == null) { + return Result.failure(FileNotFoundException("Can't find module base path")) + } + + val sdk = setupUvSdkUnderProgress(module, basePath, ProjectJdkTable.getInstance().allJdks.toList(), null) + sdk.onSuccess { + SdkConfigurationUtil.addSdk(it) + } + + return sdk + } +} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/poetry/PoetryFilesUtils.kt b/python/src/com/jetbrains/python/sdk/poetry/PoetryFilesUtils.kt index 900899e9d9ce..cdfaa1f870b1 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/PoetryFilesUtils.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/PoetryFilesUtils.kt @@ -61,7 +61,7 @@ const val POETRY_DEFAULT_SOURCE_URL: String = "https://pypi.org/simple" val LOGGER = Logger.getInstance("#com.jetbrains.python.sdk.poetry") -internal suspend fun getPyProjectTomlForPoetry(virtualFile: VirtualFile): VirtualFile? = +suspend fun getPyProjectTomlForPoetry(virtualFile: VirtualFile): VirtualFile? = withContext(Dispatchers.IO) { readAction { try {