diff --git a/python/src/com/jetbrains/python/sdk/poetry/PoetryCommandExecutor.kt b/python/src/com/jetbrains/python/sdk/poetry/PoetryCommandExecutor.kt index 7c6dcea9e17e..f2ba93e87f4f 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/PoetryCommandExecutor.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/PoetryCommandExecutor.kt @@ -32,6 +32,8 @@ import com.jetbrains.python.venvReader.VirtualEnvReader import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import io.github.z4kn4fein.semver.Version +import io.github.z4kn4fein.semver.toVersion import org.jetbrains.annotations.ApiStatus.Internal import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.SystemDependent @@ -45,6 +47,7 @@ import kotlin.io.path.pathString */ private const val REPLACE_PYTHON_VERSION = """import re,sys;f=open("pyproject.toml", "r+");orig=f.read();f.seek(0);f.write(re.sub(r"(python = \"\^)[^\"]+(\")", "\g<1>"+'.'.join(str(v) for v in sys.version_info[:2])+"\g<2>", orig))""" private val poetryNotFoundException: Throwable = Throwable(PyBundle.message("python.sdk.poetry.execution.exception.no.poetry.message")) +private val VERSION_2 = "2.0.0".toVersion() @Internal suspend fun runPoetry(projectPath: Path?, vararg args: String): Result { @@ -92,7 +95,7 @@ suspend fun validatePoetryExecutable(poetryExecutable: Path?): ValidationInfo? = */ internal suspend fun runPoetryWithSdk(sdk: Sdk, vararg args: String): Result { val projectPath = sdk.associatedModulePath?.let { Path.of(it) } ?: return Result.failure(poetryNotFoundException) // Choose a correct sdk - return reportSequentialProgress(2) { reporter -> + return reportSequentialProgress(2) { reporter -> reporter.itemStep { runPoetry(projectPath, "env", "use", sdk.homePath!!) } @@ -155,7 +158,12 @@ internal suspend fun detectPoetryEnvs(module: Module?, existingSdkPaths: Set, List>> { - // Just in case there were any changes to pyproject.toml - if (runPoetryWithSdk(sdk, "lock", "--check").isFailure) { - if (runPoetryWithSdk(sdk, "lock", "--no-update").isFailure) { - runPoetryWithSdk(sdk, "lock") + val version = getPoetryVersion()?.toVersion() + + // Ensure that the lock file is up to date. + if (!checkLock(sdk, version)) { + fixLock(sdk, version).getOrElse { + return Result.failure(it) } } @@ -224,6 +234,28 @@ suspend fun poetryListPackages(sdk: Sdk): Result, List= VERSION_2) { + return runPoetryWithSdk(sdk, "check", "--lock").isSuccess + } + + return runPoetryWithSdk(sdk, "lock", "--check").isSuccess +} + +@Internal +suspend fun fixLock(sdk: Sdk, version: Version?): Result { + if (version == null || version >= VERSION_2) { + return runPoetryWithSdk(sdk, "lock") + } + + return runPoetryWithSdk(sdk, "lock", "--no-update") +} + @Internal fun parsePoetryInstallDryRun(input: String): Pair, List> { val installedLines = listOf("Already installed", "Skipping", "Updating")