support system pythons provided by asdf; PY-32643 Ready for Merge

GitOrigin-RevId: 926ee14228644c33ab4a17247a07cdf71799b265
This commit is contained in:
Aleksandr Sorotskii
2025-07-18 20:36:53 +00:00
committed by intellij-monorepo-bot
parent ae26ded226
commit a79ea7edfd
4 changed files with 95 additions and 1 deletions
@@ -891,8 +891,10 @@
<systemPythonProvider implementation="com.intellij.python.community.services.systemPython.impl.providers.WindowsSystemPythonProvider" os="windows"/>
<systemPythonProvider implementation="com.intellij.python.community.services.systemPython.impl.providers.AsdfSystemPythonProvider"/>
<systemPythonProvider implementation="com.intellij.python.community.services.systemPython.impl.providers.PyenvSystemPythonProvider"/>
<systemPythonProvider implementation="com.intellij.python.community.services.systemPython.impl.providers.UnixSystemPythonProvider"/>
<systemPythonProvider implementation="com.intellij.python.community.services.systemPython.impl.providers.UnixSystemPythonProvider" os="unix"/>
<inspectionExtension implementation="com.jetbrains.python.sdk.configuration.suppressors.PyInterpreterInspectionSuppressor"/>
<inspectionExtension implementation="com.jetbrains.python.inspections.PyUnresolvedReferenceDefaultInspectionExtension" order="last"/>
@@ -14,6 +14,7 @@ public final class PythonCommunityServicesSystemPythonIcons {
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
return IconManager.getInstance().loadRasterizedIcon(path, PythonCommunityServicesSystemPythonIcons.class.getClassLoader(), cacheKey, flags);
}
/** 16x16 */ public static final @NotNull Icon Asdf = load("icons/com/intellij/python/community/system/providers/expui/asdf.svg", 1124514615, 0);
/** 16x16 */ public static final @NotNull Icon Homebrew = load("icons/com/intellij/python/community/system/providers/expui/homebrew.svg", -2104807435, 0);
/** 16x16 */ public static final @NotNull Icon Pyenv = load("icons/com/intellij/python/community/system/providers/expui/pyenv.svg", -770384196, 0);
}
@@ -0,0 +1,27 @@
<svg width="16" height="16" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<!-- Background circle -->
<circle cx="32" cy="32" r="30" fill="#2B2B2B" stroke="#4A90E2" stroke-width="2"/>
<!-- Python snake body -->
<path d="M15 25 Q20 20 25 25 Q30 30 35 25 Q40 20 45 25 Q50 30 55 25"
fill="none" stroke="#FFD43B" stroke-width="4" stroke-linecap="round"/>
<!-- Python snake head -->
<circle cx="52" cy="25" r="4" fill="#FFD43B"/>
<circle cx="54" cy="23" r="1" fill="#2B2B2B"/>
<!-- Version indicators (dots representing multiple versions) -->
<circle cx="20" cy="40" r="2" fill="#4A90E2"/>
<circle cx="28" cy="42" r="2" fill="#4A90E2"/>
<circle cx="36" cy="40" r="2" fill="#4A90E2"/>
<circle cx="44" cy="42" r="2" fill="#4A90E2"/>
<!-- ASDF text -->
<text x="32" y="55" text-anchor="middle" font-family="monospace" font-size="8" fill="#FFFFFF" font-weight="bold">asdf</text>
<!-- Python logo inspired elements -->
<path d="M25 15 Q30 10 35 15 Q40 20 35 25 Q30 30 25 25 Q20 20 25 15"
fill="#306998" opacity="0.7"/>
<path d="M29 15 Q34 10 39 15 Q44 20 39 25 Q34 30 29 25 Q24 20 29 15"
fill="#FFD43B" opacity="0.7"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,64 @@
// 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.impl.providers
import com.intellij.openapi.diagnostic.Logger
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.getOrNull
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.python.community.services.shared.UICustomization
import com.intellij.python.community.services.systemPython.PythonCommunityServicesSystemPythonIcons
import com.intellij.python.community.services.systemPython.SystemPythonProvider
import com.jetbrains.python.PythonBinary
import com.jetbrains.python.errorProcessing.PyResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
private class AsdfSystemPythonProvider : SystemPythonProvider {
private val LOGGER: Logger = Logger.getInstance(AsdfSystemPythonProvider::class.java)
override suspend fun findSystemPythons(eelApi: EelApi): PyResult<Set<PythonBinary>> {
if (useLegacyPythonProvider()) {
return PyResult.success(emptySet())
}
val pythons = withContext(Dispatchers.IO) {
try {
val env = eelApi.exec.fetchLoginShellEnvVariables()
val asdfRoot = if ("ASDF_DATA_DIR" in env) {
EelPath.parse(env["ASDF_DATA_DIR"]!!, eelApi.descriptor)
}
else {
eelApi.userInfo.home.resolve(".asdf")
}
val versionsDir = asdfRoot.resolve("installs").resolve("python")
val entries = eelApi.fs.listDirectory(versionsDir)
.getOrNull()
if (entries == null) {
return@withContext emptySet()
}
val paths = entries
.map { versionsDir.resolve(it).resolve("bin").asNioPath() }
return@withContext collectPythonsInPaths(eelApi, paths, listOf(python3NamePattern))
}
catch (e: RuntimeException) {
LOGGER.error("failed to discover asdf pythons", e)
}
return@withContext emptySet()
}
return PyResult.success(pythons)
}
override val uiCustomization: UICustomization?
get() {
// TODO: proper icon
return UICustomization(title = "asdf", icon = PythonCommunityServicesSystemPythonIcons.Asdf)
}
}