From 8bf5f7f51e34f806f4ab562453097f714fd976a9 Mon Sep 17 00:00:00 2001 From: TimurMalanin Date: Tue, 10 Mar 2026 21:34:36 +0000 Subject: [PATCH] PY-88148 PY-88157 Fix gray package colors for non-uv/poetry. Now getDeclaredPackageNames() from PythonPackageManager returns extracted declared deps for pyprojec.toml managers and all installed names for others. Added refresh of packages in PTW after removing some pkg. (cherry picked from commit 7942e4274aaadbf1c8b6ebce5abe27294624d41d) IJ-MR-195246 GitOrigin-RevId: 53348fcd3ec2ddb4d7678421898ba05079341298 --- .../packaging/management/PythonPackageManager.kt | 12 +++++++++++- .../toolwindow/PyPackagingToolWindowService.kt | 11 +++++++---- .../python/sdk/poetry/PoetryPackageManager.kt | 2 +- .../com/jetbrains/python/sdk/uv/UvPackageManager.kt | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/management/PythonPackageManager.kt b/python/src/com/jetbrains/python/packaging/management/PythonPackageManager.kt index b935fac3ee3d..6beb289eeae3 100644 --- a/python/src/com/jetbrains/python/packaging/management/PythonPackageManager.kt +++ b/python/src/com/jetbrains/python/packaging/management/PythonPackageManager.kt @@ -59,7 +59,17 @@ import kotlin.jvm.Throws * @see com.jetbrains.python.packaging.management.ui.PythonPackageManagerUI to execute commands with UI handlers */ @ApiStatus.Experimental -abstract class PythonPackageManager(val project: Project, val sdk: Sdk) : Disposable.Default { +abstract class PythonPackageManager @ApiStatus.Internal constructor( + val project: Project, + val sdk: Sdk, + /** + * Whether this manager has an explicit list of top-level dependencies (e.g. from pyproject.toml). + * When true, only packages from [extractDependenciesCached] are treated as "declared" in the UI, + * and the rest are shown as transitive. + * When false (default), all installed packages are considered declared. + */ + internal val installedMightBeTransitive: Boolean = false, +) : Disposable.Default { private val isInited = AtomicBoolean(false) private val initializationJob = PyPackageCoroutine.launch(project, NON_INTERACTIVE_ROOT_TRACE_CONTEXT, start = CoroutineStart.LAZY) { initInstalledPackages() diff --git a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt index 0c8516b88b19..27863787544d 100644 --- a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt +++ b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt @@ -294,6 +294,7 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou text = message("python.packaging.notification.deleted", selectedPackages.joinToString(", ") { it.name }), displayId = PYTHON_PACKAGE_DELETED ) + refreshInstalledPackages() toolWindowPanel?.clearFocus() } } @@ -394,10 +395,12 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou suspend fun refreshInstalledPackages() { val context = sdkContext ?: return - val declaredPackageNames = context.manager.extractDependenciesCached() - ?.getOrNull() - ?.map { it.name }?.toSet() - ?: emptySet() + val declaredPackageNames = if (context.manager.installedMightBeTransitive) { + context.manager.extractDependenciesCached()?.getOrNull() ?: emptyList() + } + else { + context.manager.listInstalledPackages() + }.mapTo(mutableSetOf()) { it.name } withContext(Dispatchers.Default) { val packageIndex = PackageIndex(context.manager) diff --git a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt index eb833c9a6e4d..c1242389e401 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt @@ -25,7 +25,7 @@ import org.jetbrains.annotations.TestOnly import java.nio.file.Path @ApiStatus.Internal -class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(project, sdk) { +class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(project, sdk, installedMightBeTransitive = true) { override val repositoryManager: PythonRepositoryManager = PipRepositoryManager.getInstance(project) override suspend fun syncCommand(): PyResult { diff --git a/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt b/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt index cd3265171f97..319ab245cbe4 100644 --- a/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt +++ b/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt @@ -31,7 +31,7 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -internal class UvPackageManager(project: Project, sdk: Sdk, uvExecutionContextDeferred: Deferred>) : PythonPackageManager(project, sdk) { +internal class UvPackageManager(project: Project, sdk: Sdk, uvExecutionContextDeferred: Deferred>) : PythonPackageManager(project, sdk, installedMightBeTransitive = true) { override val repositoryManager: PythonRepositoryManager = PipRepositoryManager.getInstance(project) private lateinit var uvLowLevel: PyResult> private val uvExecutionContextDeferred = uvExecutionContextDeferred.also { it.cancelOnDispose(this) }