mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[python] PY-84777 Use system pythons as a fallback for SDK configuration
There was a problem with detecting system-wide pythons, which relied on binary not being a part of conda env or virtualenv. But it led to unrelated Hatch and Poetry pythons automatically configured as interpreters in new projects. Another problem is that free-threaded python was chosen as default interpreter with highest priority because of the newest version. This change uses SystemPythonService to detect system pythons properly, also free-threaded python used as a default interpreter only if it's the only available option. Merge-request: IJ-MR-179008 Merged-by: Alexey Katsman <alexey.katsman@jetbrains.com> GitOrigin-RevId: 73bc98aed2918c44832b57f22b86c9c7d17a4301
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9140cb4e7b
commit
a03643bb9c
+18
-18
@@ -4,16 +4,16 @@ package com.intellij.python.community.services.internal.impl
|
||||
import com.intellij.platform.eel.EelPlatform
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.python.community.execService.python.validatePythonAndGetVersion
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl.Companion.concurrentLimit
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl.Companion.createByPythonBinary
|
||||
import com.intellij.python.community.services.shared.LanguageLevelComparator
|
||||
import com.intellij.python.community.services.shared.PythonWithLanguageLevel
|
||||
import com.intellij.python.community.services.shared.VanillaPythonWithLanguageLevel
|
||||
import com.intellij.python.community.execService.python.validatePythonAndGetInfo
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl.Companion.concurrentLimit
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl.Companion.createByPythonBinary
|
||||
import com.intellij.python.community.services.shared.PythonInfoComparator
|
||||
import com.intellij.python.community.services.shared.PythonWithPythonInfo
|
||||
import com.intellij.python.community.services.shared.VanillaPythonWithPythonInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.PythonInfo
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
@@ -25,10 +25,10 @@ import kotlin.io.path.pathString
|
||||
import kotlin.io.path.relativeTo
|
||||
|
||||
@Internal
|
||||
class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
class VanillaPythonWithPythonInfoImpl internal constructor(
|
||||
override val pythonBinary: PythonBinary,
|
||||
override val languageLevel: LanguageLevel,
|
||||
) : VanillaPythonWithLanguageLevel, Comparable<PythonWithLanguageLevel> {
|
||||
override val pythonInfo: PythonInfo,
|
||||
) : VanillaPythonWithPythonInfo, Comparable<PythonWithPythonInfo> {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -38,7 +38,7 @@ class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
* Like [createByPythonBinary] but runs in parallel up to [concurrentLimit]
|
||||
* @return python path -> python with language level sorted from highest to lowest.
|
||||
*/
|
||||
suspend fun createByPythonBinaries(pythonBinaries: Collection<PythonBinary>): Collection<Pair<PythonBinary, PyResult<VanillaPythonWithLanguageLevel>>> =
|
||||
suspend fun createByPythonBinaries(pythonBinaries: Collection<PythonBinary>): Collection<Pair<PythonBinary, PyResult<VanillaPythonWithPythonInfo>>> =
|
||||
coroutineScope {
|
||||
pythonBinaries.map {
|
||||
async {
|
||||
@@ -49,9 +49,9 @@ class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
}.awaitAll()
|
||||
}.sortedBy { it.first }
|
||||
|
||||
suspend fun createByPythonBinary(pythonBinary: PythonBinary): PyResult<VanillaPythonWithLanguageLevelImpl> {
|
||||
val languageLevel = pythonBinary.validatePythonAndGetVersion().getOr { return it }
|
||||
return Result.success(VanillaPythonWithLanguageLevelImpl(pythonBinary, languageLevel))
|
||||
suspend fun createByPythonBinary(pythonBinary: PythonBinary): PyResult<VanillaPythonWithPythonInfoImpl> {
|
||||
val pythonInfo = pythonBinary.validatePythonAndGetInfo().getOr { return it }
|
||||
return Result.success(VanillaPythonWithPythonInfoImpl(pythonBinary, pythonInfo))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as VanillaPythonWithLanguageLevelImpl
|
||||
other as VanillaPythonWithPythonInfoImpl
|
||||
|
||||
return pythonBinary == other.pythonBinary
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$pythonBinary ($languageLevel)"
|
||||
return "$pythonBinary ($pythonInfo)"
|
||||
}
|
||||
|
||||
override suspend fun getReadableName(): @Nls String {
|
||||
@@ -81,8 +81,8 @@ class VanillaPythonWithLanguageLevelImpl internal constructor(
|
||||
}
|
||||
val pythonString = (if (pythonBinary.startsWith(home)) "~$separator" + pythonBinary.relativeTo(home).pathString
|
||||
else pythonBinary.pathString)
|
||||
return "$pythonString ($languageLevel)"
|
||||
return "$pythonString ($pythonInfo)"
|
||||
}
|
||||
|
||||
override fun compareTo(other: PythonWithLanguageLevel): Int = LanguageLevelComparator.compare(this, other)
|
||||
override fun compareTo(other: PythonWithPythonInfo): Int = PythonInfoComparator.compare(this, other)
|
||||
}
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
// 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.junit5Tests.env.services.internal.impl
|
||||
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl
|
||||
import com.intellij.python.junit5Tests.framework.env.PyEnvTestCase
|
||||
import com.intellij.python.junit5Tests.framework.env.PythonBinaryPath
|
||||
import com.intellij.python.junit5Tests.randomBinary
|
||||
@@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test
|
||||
class PythonWithLanguageLevelImplTest {
|
||||
@Test
|
||||
fun testRainyDay(): Unit = runBlocking {
|
||||
when (val r = VanillaPythonWithLanguageLevelImpl.createByPythonBinary(randomBinary)) {
|
||||
when (val r = VanillaPythonWithPythonInfoImpl.createByPythonBinary(randomBinary)) {
|
||||
is Result.Failure -> Unit
|
||||
is Result.Success -> fail("Unexpected success ${r.result}")
|
||||
}
|
||||
@@ -23,8 +23,8 @@ class PythonWithLanguageLevelImplTest {
|
||||
|
||||
@Test
|
||||
fun testSunnyDay(@PythonBinaryPath pythonBinary: PythonBinary): Unit = runBlocking {
|
||||
val python = VanillaPythonWithLanguageLevelImpl.createByPythonBinary(pythonBinary).orThrow()
|
||||
val python = VanillaPythonWithPythonInfoImpl.createByPythonBinary(pythonBinary).orThrow()
|
||||
assertEquals(pythonBinary, python.pythonBinary, "Wrong python binary")
|
||||
assertTrue(python.languageLevel.isPy3K, "Wrong python version")
|
||||
assertTrue(python.pythonInfo.languageLevel.isPy3K, "Wrong python version")
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -1,8 +1,9 @@
|
||||
// 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.junit5Tests.unit
|
||||
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.jetbrains.python.PythonInfo
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import org.junit.jupiter.api.Assertions.assertArrayEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -14,12 +15,12 @@ class CompareByLanguageLevelTest {
|
||||
@Test
|
||||
fun testCompareByLanguageLevel(@TempDir path: Path) {
|
||||
val list = listOf(
|
||||
VanillaPythonWithLanguageLevelImpl(path, LanguageLevel.PYTHON38),
|
||||
VanillaPythonWithLanguageLevelImpl(path, LanguageLevel.PYTHON312),
|
||||
VanillaPythonWithLanguageLevelImpl(path, LanguageLevel.PYTHON311),
|
||||
VanillaPythonWithPythonInfoImpl(path, PythonInfo(LanguageLevel.PYTHON38)),
|
||||
VanillaPythonWithPythonInfoImpl(path, PythonInfo(LanguageLevel.PYTHON312)),
|
||||
VanillaPythonWithPythonInfoImpl(path, PythonInfo(LanguageLevel.PYTHON311)),
|
||||
)
|
||||
|
||||
val sortedLevels = list.sorted().map { it.languageLevel }.toTypedArray()
|
||||
val sortedLevels = list.sorted().map { it.pythonInfo.languageLevel }.toTypedArray()
|
||||
assertArrayEquals(arrayOf(LanguageLevel.PYTHON312, LanguageLevel.PYTHON311, LanguageLevel.PYTHON38), sortedLevels,
|
||||
"Highest python goes first")
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,8 +1,9 @@
|
||||
// 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.junit5Tests.unit.alsoWin.services.internal.impl
|
||||
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.jetbrains.python.PythonInfo
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
@@ -23,7 +24,7 @@ class ReadableNameTest {
|
||||
@Test
|
||||
fun testNoHomePath(@TempDir path: Path): Unit = runBlocking {
|
||||
val fakePython = path.resolve(PYTHON_FILE_NAME)
|
||||
val name = VanillaPythonWithLanguageLevelImpl(fakePython, LanguageLevel.PYTHON312).getReadableName()
|
||||
val name = VanillaPythonWithPythonInfoImpl(fakePython, PythonInfo(LanguageLevel.PYTHON312)).getReadableName()
|
||||
assertThat("Wrong name generated", name, allOf(containsString("3.12"), containsString(fakePython.pathString)))
|
||||
}
|
||||
|
||||
@@ -33,11 +34,11 @@ class ReadableNameTest {
|
||||
|
||||
|
||||
var fakePython = home.resolve(PYTHON_FILE_NAME)
|
||||
var name = VanillaPythonWithLanguageLevelImpl(fakePython, LanguageLevel.PYTHON312).getReadableName()
|
||||
var name = VanillaPythonWithPythonInfoImpl(fakePython, PythonInfo(LanguageLevel.PYTHON312)).getReadableName()
|
||||
assertThat("Wrong name generated", name, allOf(containsString("3.12"), matchesPattern(".*~[\\\\/]$PYTHON_FILE_NAME.*")))
|
||||
|
||||
fakePython = home.resolve("deep").resolve(PYTHON_FILE_NAME)
|
||||
name = VanillaPythonWithLanguageLevelImpl(fakePython, LanguageLevel.PYTHON312).getReadableName()
|
||||
name = VanillaPythonWithPythonInfoImpl(fakePython, PythonInfo(LanguageLevel.PYTHON312)).getReadableName()
|
||||
assertThat("Wrong name generated", name, allOf(containsString("3.12"), matchesPattern(".*~[\\\\/]deep[\\\\/]$PYTHON_FILE_NAME.*")))
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
// 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.shared
|
||||
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import com.jetbrains.python.PythonInfo
|
||||
|
||||
/**
|
||||
* Something with language level
|
||||
* Something with python info
|
||||
*/
|
||||
interface LanguageLevelHolder {
|
||||
val languageLevel: LanguageLevel
|
||||
interface PythonInfoHolder {
|
||||
val pythonInfo: PythonInfo
|
||||
}
|
||||
+2
-2
@@ -4,9 +4,9 @@ package com.intellij.python.community.services.shared
|
||||
import com.intellij.python.community.execService.python.advancedApi.ExecutablePython
|
||||
|
||||
/**
|
||||
* Python (vanilla, conda, whatever) with known language level.
|
||||
* Python (vanilla, conda, whatever) with known python info.
|
||||
*/
|
||||
interface PythonWithLanguageLevel : PythonWithName, LanguageLevelHolder {
|
||||
interface PythonWithPythonInfo : PythonWithName, PythonInfoHolder {
|
||||
|
||||
/**
|
||||
* Convert python to something that can be executed on [java.util.concurrent.ExecutorService]
|
||||
+2
-2
@@ -2,6 +2,6 @@
|
||||
package com.intellij.python.community.services.shared
|
||||
|
||||
/**
|
||||
* Python that has both [languageLevel] and [ui]
|
||||
* Python that has both [pythonInfo] and [ui]
|
||||
*/
|
||||
interface PythonWithUi : PythonWithLanguageLevel, UiHolder
|
||||
interface PythonWithUi : PythonWithPythonInfo, UiHolder
|
||||
+1
-1
@@ -8,7 +8,7 @@ import com.jetbrains.python.PythonBinary
|
||||
/**
|
||||
* Vanilla (not conda) has [pythonBinary]
|
||||
*/
|
||||
interface VanillaPythonWithLanguageLevel : PythonWithLanguageLevel {
|
||||
interface VanillaPythonWithPythonInfo : PythonWithPythonInfo {
|
||||
val pythonBinary: PythonBinary
|
||||
override val asExecutablePython: ExecutablePython get() = ExecutablePython.vanillaExecutablePython(pythonBinary)
|
||||
|
||||
+14
-14
@@ -3,22 +3,11 @@ package com.intellij.python.community.services.shared
|
||||
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import java.util.*
|
||||
|
||||
|
||||
private val logger = fileLogger()
|
||||
|
||||
object LanguageLevelComparator : Comparator<LanguageLevelHolder> {
|
||||
override fun compare(o1: LanguageLevelHolder, o2: LanguageLevelHolder): Int {
|
||||
// Backward: first python is the highest
|
||||
if (logger.isDebugEnabled) {
|
||||
logger.debug("langLevel ${o1.languageLevel} vs ${o2.languageLevel}")
|
||||
}
|
||||
return LanguageLevel.VERSION_COMPARATOR.compare(o1.languageLevel, o2.languageLevel) * -1
|
||||
}
|
||||
}
|
||||
|
||||
object UiComparator : Comparator<UiHolder> {
|
||||
override fun compare(o1: UiHolder, o2: UiHolder): Int {
|
||||
if (logger.isDebugEnabled) {
|
||||
@@ -28,13 +17,24 @@ object UiComparator : Comparator<UiHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageLevelWithUiComparator<T> : Comparator<T> where T : LanguageLevelHolder, T : UiHolder {
|
||||
object PythonInfoComparator : Comparator<PythonInfoHolder> {
|
||||
override fun compare(o1: PythonInfoHolder, o2: PythonInfoHolder): Int {
|
||||
// Backward: first python is the highest
|
||||
if (logger.isDebugEnabled) {
|
||||
logger.debug("pythonInfo ${o1.pythonInfo} vs ${o2.pythonInfo}")
|
||||
}
|
||||
return o1.pythonInfo.compareTo(o2.pythonInfo)
|
||||
}
|
||||
}
|
||||
|
||||
class PythonInfoWithUiComparator<T> : Comparator<T> where T : PythonInfoHolder, T : UiHolder {
|
||||
override fun compare(o1: T, o2: T): Int {
|
||||
if (logger.isDebugEnabled) {
|
||||
logger.debug("full ${o1.string()} vs ${o2.string()}")
|
||||
}
|
||||
return LanguageLevelComparator.compare(o1, o2) * 10 + UiComparator.compare(o1, o2)
|
||||
return PythonInfoComparator.compare(o1, o2) * 10 + UiComparator.compare(o1, o2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> T.string(): String where T : LanguageLevelHolder, T : UiHolder = "($languageLevel,${ui?.toolName})"
|
||||
private fun <T> T.string(): String where T : PythonInfoHolder, T : UiHolder =
|
||||
"(${pythonInfo.languageLevel},${ui?.toolName},free-threaded:${pythonInfo.freeThreaded})"
|
||||
|
||||
+26
-21
@@ -1,10 +1,11 @@
|
||||
// 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.junit5Tests.unit.comparators
|
||||
|
||||
import com.intellij.python.community.services.shared.LanguageLevelHolder
|
||||
import com.intellij.python.community.services.shared.LanguageLevelWithUiComparator
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.intellij.python.community.services.shared.PythonInfoHolder
|
||||
import com.intellij.python.community.services.shared.PythonInfoWithUiComparator
|
||||
import com.intellij.python.community.services.shared.UiHolder
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonInfo
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import org.hamcrest.MatcherAssert
|
||||
import org.hamcrest.Matchers
|
||||
@@ -16,29 +17,33 @@ class ComparatorsTest {
|
||||
@Test
|
||||
fun testComparators() {
|
||||
val mocks = arrayOf(
|
||||
MockLevel(LanguageLevel.PYTHON314),
|
||||
MockLevel(LanguageLevel.PYTHON310),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("A")),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("Z")),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("B")),
|
||||
MockLevel(LanguageLevel.PYTHON27),
|
||||
MockLevel(LanguageLevel.PYTHON313),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON314)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON314, true)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("A")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("Z")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("B")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON27)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON313, true)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON313)),
|
||||
)
|
||||
val set = TreeSet(LanguageLevelWithUiComparator<MockLevel>())
|
||||
val set = TreeSet(PythonInfoWithUiComparator<MockInfo>())
|
||||
set.addAll(mocks)
|
||||
MatcherAssert.assertThat("", set, Matchers.contains(
|
||||
MockLevel(LanguageLevel.PYTHON314),
|
||||
MockLevel(LanguageLevel.PYTHON313),
|
||||
MockLevel(LanguageLevel.PYTHON310),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("A")),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("B")),
|
||||
MockLevel(LanguageLevel.PYTHON310, ui = PyToolUIInfo("Z")),
|
||||
MockLevel(LanguageLevel.PYTHON27)
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON314)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON314, true)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON313)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON313, true)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310)),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("A")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("B")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON310), ui = PyToolUIInfo("Z")),
|
||||
MockInfo(PythonInfo(LanguageLevel.PYTHON27))
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
private data class MockLevel(
|
||||
override val languageLevel: LanguageLevel,
|
||||
private data class MockInfo(
|
||||
override val pythonInfo: PythonInfo,
|
||||
override val ui: PyToolUIInfo? = null,
|
||||
) : LanguageLevelHolder, UiHolder
|
||||
) : PythonInfoHolder, UiHolder
|
||||
|
||||
+4
-4
@@ -6,9 +6,9 @@ import com.intellij.openapi.components.service
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.impl.venv.createVenv
|
||||
import com.intellij.python.community.services.shared.LanguageLevelWithUiComparator
|
||||
import com.intellij.python.community.services.shared.PythonInfoWithUiComparator
|
||||
import com.intellij.python.community.services.shared.PythonWithUi
|
||||
import com.intellij.python.community.services.shared.VanillaPythonWithLanguageLevel
|
||||
import com.intellij.python.community.services.shared.VanillaPythonWithPythonInfo
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
@@ -56,10 +56,10 @@ fun SystemPythonService(): SystemPythonService = ApplicationManager.getApplicati
|
||||
*
|
||||
* Instances could be obtained with [SystemPythonService]
|
||||
*/
|
||||
class SystemPython internal constructor(private val delegate: VanillaPythonWithLanguageLevel, override val ui: PyToolUIInfo?) : VanillaPythonWithLanguageLevel by delegate, PythonWithUi, Comparable<SystemPython> {
|
||||
class SystemPython internal constructor(private val delegate: VanillaPythonWithPythonInfo, override val ui: PyToolUIInfo?) : VanillaPythonWithPythonInfo by delegate, PythonWithUi, Comparable<SystemPython> {
|
||||
|
||||
private companion object {
|
||||
val comparator = LanguageLevelWithUiComparator<SystemPython>()
|
||||
val comparator = PythonInfoWithUiComparator<SystemPython>()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
+5
-5
@@ -11,12 +11,12 @@ import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.impl.installer.PySdkToInstallManager
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithLanguageLevelImpl
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.intellij.python.community.services.internal.impl.VanillaPythonWithPythonInfoImpl
|
||||
import com.intellij.python.community.services.systemPython.SystemPythonServiceImpl.MyServiceState
|
||||
import com.intellij.python.community.services.systemPython.impl.Cache
|
||||
import com.intellij.python.community.services.systemPython.impl.PySystemPythonBundle
|
||||
import com.jetbrains.python.NON_INTERACTIVE_ROOT_TRACE_CONTEXT
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
@@ -66,7 +66,7 @@ internal class SystemPythonServiceImpl(scope: CoroutineScope) : SystemPythonServ
|
||||
}
|
||||
|
||||
override suspend fun registerSystemPython(pythonPath: PythonBinary): PyResult<SystemPython> {
|
||||
val pythonWithLangLevel = VanillaPythonWithLanguageLevelImpl.createByPythonBinary(pythonPath)
|
||||
val pythonWithLangLevel = VanillaPythonWithPythonInfoImpl.createByPythonBinary(pythonPath)
|
||||
.getOr(PySystemPythonBundle.message("py.system.python.service.python.is.broken", pythonPath)) { return it }
|
||||
val systemPython = SystemPython(pythonWithLangLevel, null)
|
||||
state.userProvidedPythons.add(pythonPath.pathString)
|
||||
@@ -124,7 +124,7 @@ internal class SystemPythonServiceImpl(scope: CoroutineScope) : SystemPythonServ
|
||||
val badPythons = mutableSetOf<PythonBinary>()
|
||||
val pythons = pythonsFromExtensions + state.userProvidedPythonsAsPath.filter { it.getEelDescriptor() == eelApi.descriptor }
|
||||
|
||||
val result = VanillaPythonWithLanguageLevelImpl.createByPythonBinaries(pythons.toSet())
|
||||
val result = VanillaPythonWithPythonInfoImpl.createByPythonBinaries(pythons.toSet())
|
||||
.mapNotNull { (python, r) ->
|
||||
when (r) {
|
||||
is Result.Success -> SystemPython(r.result, pythonsUi[r.result.pythonBinary])
|
||||
@@ -159,4 +159,4 @@ private object LocalPythonInstaller : PythonInstallerService {
|
||||
}
|
||||
return Result.Companion.success(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -13,7 +13,8 @@ class Py27Test {
|
||||
@Test
|
||||
fun testPy27(): Unit = timeoutRunBlocking {
|
||||
val testEnvironments = SystemPythonService().findSystemPythons()
|
||||
val python27 = testEnvironments.firstOrNull { it.languageLevel == LanguageLevel.PYTHON27 } ?: error("No 2.7 found in $testEnvironments")
|
||||
val python27 = testEnvironments.firstOrNull { it.pythonInfo.languageLevel == LanguageLevel.PYTHON27 }
|
||||
?: error("No 2.7 found in $testEnvironments")
|
||||
SystemPythonService().registerSystemPython(python27.pythonBinary).getOrThrow()
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -5,6 +5,7 @@ import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.ExecuteProcessException
|
||||
import com.intellij.platform.eel.ThrowsChecked
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
@@ -23,8 +24,11 @@ import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.junit5.RegistryKey
|
||||
import com.intellij.testFramework.junit5.TestDisposable
|
||||
import com.intellij.testFramework.registerExtension
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.MessageError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.getOrThrow
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
|
||||
import com.jetbrains.python.venvReader.VirtualEnvReader
|
||||
@@ -35,10 +39,6 @@ import org.hamcrest.Matchers.not
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.deleteExisting
|
||||
import kotlin.io.path.pathString
|
||||
@@ -55,11 +55,11 @@ class SystemPythonServiceShowCaseTest {
|
||||
val eelApi = systemPython.pythonBinary.getEelDescriptor().toEelApi()
|
||||
val process = eelApi.exec.spawnProcess(systemPython.pythonBinary.pathString, "--version").eelIt()
|
||||
val output = async {
|
||||
(if (systemPython.languageLevel.isPy3K) process.stdout else process.stderr).readWholeText()
|
||||
(if (systemPython.pythonInfo.languageLevel.isPy3K) process.stdout else process.stderr).readWholeText()
|
||||
}
|
||||
Assertions.assertTrue(process.exitCode.await() == 0)
|
||||
val versionString = PythonSdkFlavor.getLanguageLevelFromVersionStringStaticSafe(output.await())!!
|
||||
Assertions.assertEquals(systemPython.languageLevel, versionString, "Wrong version")
|
||||
Assertions.assertEquals(systemPython.pythonInfo.languageLevel, versionString, "Wrong version")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -3,8 +3,8 @@ package com.intellij.python.junit5Tests.env.systemPython.impl
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.python.community.impl.venv.createVenv
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.intellij.python.community.services.systemPython.SystemPythonProvider
|
||||
import com.intellij.python.community.services.systemPython.SystemPythonService
|
||||
import com.intellij.python.junit5Tests.framework.env.PyEnvTestCase
|
||||
@@ -12,6 +12,7 @@ import com.intellij.python.junit5Tests.framework.env.PythonBinaryPath
|
||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.junit5.TestDisposable
|
||||
import com.intellij.testFramework.registerExtension
|
||||
import com.jetbrains.python.PyToolUIInfo
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.getOrThrow
|
||||
@@ -20,7 +21,6 @@ import org.hamcrest.Matchers
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import java.nio.file.Path
|
||||
|
||||
@PyEnvTestCase
|
||||
@@ -35,7 +35,7 @@ class EnvProviderTest {
|
||||
if (systemPythons.size > 1) {
|
||||
val best = systemPythons.first()
|
||||
for (python in systemPythons.subList(1, systemPythonBinaries.size)) {
|
||||
assertTrue(python.languageLevel <= best.languageLevel, "$best is the first, bust worse than $python")
|
||||
assertTrue(python.pythonInfo.languageLevel <= best.pythonInfo.languageLevel, "$best is the first, bust worse than $python")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class EnvProviderTest {
|
||||
|
||||
private class InlineTestProvider(
|
||||
private val pythons: Set<PythonBinary>,
|
||||
override val uiCustomization: PyToolUIInfo?
|
||||
override val uiCustomization: PyToolUIInfo?,
|
||||
) : SystemPythonProvider {
|
||||
override suspend fun findSystemPythons(eelApi: EelApi) = Result.success(pythons)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user