PY-87191 Always provide system Python when setting up Poetry environment

- Extract PyVersionSpecifiers from Poetry-specific PoetryPythonVersion
  into python-community-openapi for reuse across subsystems
- Add PyVersionSpecifiers parameter to PythonInstallerService.installLatestPython()
  so installation respects pyproject.toml version constraints
- Pass version specifiers from getSystemPython() through to the installer
- Move pyproject.toml python-version parsing to pyproject PSI utilities
- Replace PoetryPyProjectTomlPythonVersionsService internals with PyVersionSpecifiers


(cherry picked from commit 5ef8f7cb3430826ee38cd80ab460ea4a52da919a)

IJ-MR-193218

GitOrigin-RevId: a989e2dffd5b3081db526b703f9cc6085eac96d5
This commit is contained in:
Vitaly Legchilkin
2026-02-26 12:50:57 +00:00
committed by intellij-monorepo-bot
parent e71389d8b8
commit eab2b8b719
14 changed files with 530 additions and 148 deletions
@@ -19,6 +19,7 @@ import com.jetbrains.python.errorProcessing.MessageError
import com.jetbrains.python.errorProcessing.PyError
import com.jetbrains.python.errorProcessing.PyResult
import com.jetbrains.python.mapError
import com.jetbrains.python.packaging.PyVersionSpecifiers
import com.jetbrains.python.venvReader.Directory
import com.jetbrains.python.venvReader.VirtualEnvReader
import org.jetbrains.annotations.ApiStatus
@@ -142,9 +143,18 @@ interface PythonInstallerService {
* Returns Unit for now (so you should call [SystemPythonService.findSystemPythons]), but this is a subject to change.
*/
@ApiStatus.Experimental
suspend fun installLatestPython(): Result<Unit, String>
suspend fun installLatestPython(
versionSpecifiers: PyVersionSpecifiers = PyVersionSpecifiers.ANY_SUPPORTED,
): Result<Unit, String>
}
/**
* Finds the first [SystemPython] matching the given [specifiers].
*/
@Internal
fun List<SystemPython>.findMatchingPython(specifiers: PyVersionSpecifiers = PyVersionSpecifiers.ANY_SUPPORTED): SystemPython? =
firstOrNull { specifiers.isValid(it.pythonInfo.languageLevel) }
/**
* See [createVenv]
*/
@@ -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.intellij.python.community.services.systemPython
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.components.RoamingType
@@ -31,8 +30,8 @@ import com.jetbrains.python.PythonBinary
import com.jetbrains.python.Result
import com.jetbrains.python.errorProcessing.getOr
import com.jetbrains.python.getOrNull
import com.jetbrains.python.packaging.PyVersionSpecifiers
import com.jetbrains.python.sdk.installer.installBinary
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -191,11 +190,12 @@ class SystemPythonServiceImpl internal constructor(
private object LocalPythonInstaller : PythonInstallerService {
override suspend fun installLatestPython(): Result<Unit, String> {
val pythonToInstall =
withContext(Dispatchers.IO) {
PySdkToInstallManager.getAvailableVersionsToInstall().toSortedMap().values.last()
}
override suspend fun installLatestPython(versionSpecifiers: PyVersionSpecifiers): Result<Unit, String> {
val pythonToInstall = withContext(Dispatchers.IO) {
PySdkToInstallManager.getAvailableVersionsToInstall()
.filterKeys { versionSpecifiers.isValid(it) }
.maxByOrNull { it.key }?.value
} ?: return Result.Companion.failure("No matching Python version available for installation")
withContext(Dispatchers.EDT) {
installBinary(pythonToInstall, null) {
}