From 2873bad6183e24dbcaac5779b664fe9b5b3721d1 Mon Sep 17 00:00:00 2001 From: Aleksandr Sorotskii Date: Thu, 9 Jan 2025 19:06:02 +0100 Subject: [PATCH] fix notification for installing packages via quickfix; #PY-72070 Fixed (cherry picked from commit bee8b1c0431c186658c11b2f0fb33f4c26f95fee) GitOrigin-RevId: 14417efa3be6f4785fbdf1b05505c7efd09f3a20 --- .../python/packaging/PyPackageManagerUI.java | 10 +++- ...llerAsync.kt => PythonPackageInstaller.kt} | 60 +++++++++++-------- 2 files changed, 42 insertions(+), 28 deletions(-) rename python/src/com/jetbrains/python/packaging/management/{PythonPackageInstallerAsync.kt => PythonPackageInstaller.kt} (55%) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerUI.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerUI.java index 523f99bb0f61..7a2e4211d631 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerUI.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerUI.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; +import com.jetbrains.python.packaging.management.PythonPackagesInstaller; import com.jetbrains.python.packaging.ui.PyPackageManagementService; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -259,18 +260,23 @@ public final class PyPackageManagerUI { @Override protected @NotNull List runTask(@NotNull ProgressIndicator indicator) { final List exceptions = new ArrayList<>(); - if (myProject == null) { + // FIXME: proper error return exceptions; } - PythonPackagesInstallerAsync.Companion.installPackages( + var result = PythonPackagesInstaller.Companion.installPackages( myProject, myRequirements, myExtraArgs, indicator ); + // FIXME: use packaging tool window service for managing error dialog + if (result != null) { + exceptions.add(result); + } + return exceptions; } diff --git a/python/src/com/jetbrains/python/packaging/management/PythonPackageInstallerAsync.kt b/python/src/com/jetbrains/python/packaging/management/PythonPackageInstaller.kt similarity index 55% rename from python/src/com/jetbrains/python/packaging/management/PythonPackageInstallerAsync.kt rename to python/src/com/jetbrains/python/packaging/management/PythonPackageInstaller.kt index 38c60681b75a..60dde9ddda8f 100644 --- a/python/src/com/jetbrains/python/packaging/management/PythonPackageInstallerAsync.kt +++ b/python/src/com/jetbrains/python/packaging/management/PythonPackageInstaller.kt @@ -1,62 +1,77 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.python.packaging +import com.intellij.execution.ExecutionException import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.runBlockingCancellable import com.intellij.openapi.project.Project import com.jetbrains.python.PyBundle -import com.jetbrains.python.packaging.common.PythonPackageSpecification +import com.jetbrains.python.packaging.PyRequirement import com.jetbrains.python.packaging.common.PythonPackageSpecificationBase import com.jetbrains.python.packaging.common.PythonSimplePackageSpecification -import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch - -class PythonPackagesInstallerAsync { +class PythonPackagesInstaller { companion object { + @JvmStatic fun installPackages( project: Project, requirements: List?, extraArgs: List, indicator: ProgressIndicator, - ) { - val packageService = PyPackagingToolWindowService.getInstance(project) + ): ExecutionException? { + runBlockingCancellable { + val manager = PythonPackageManager.forSdk(project, sdk) + // FIXME: encapsulate into forSdk + manager.repositoryManager.refreshCashes() - packageService.serviceScope.launch(Dispatchers.IO) { - if (requirements.isNullOrEmpty()) { - installWithoutRequirements(packageService, extraArgs, indicator) + return@runBlockingCancellable if (requirements.isNullOrEmpty()) { + installWithoutRequirements(manager, extraArgs, indicator) } else { - installWithRequirements(packageService, requirements, extraArgs, indicator) + installWithRequirements(manager, requirements, extraArgs, indicator) } + }.exceptionOrNull()?.let { + return ExecutionException(it) } + + return null } private suspend fun installWithoutRequirements( - packageService: PyPackagingToolWindowService, + manager: PythonPackageManager, extraArgs: List, indicator: ProgressIndicator, - ) { + ): Result { indicator.text = PyBundle.message("python.packaging.installing.packages") indicator.isIndeterminate = true + // LAME: extra args seems to be package names - convert them val emptySpecification = PythonPackageSpecificationBase("", null, null, null) - packageService.installPackage(emptySpecification, extraArgs) + manager.installPackage(emptySpecification, extraArgs).getOrElse { + return Result.failure(it) + } + + return Result.success(Unit) } private suspend fun installWithRequirements( - packageService: PyPackagingToolWindowService, + manager: PythonPackageManager, requirements: List, extraArgs: List, indicator: ProgressIndicator, - ) { + ): Result { requirements.forEachIndexed { index, requirement -> indicator.text = PyBundle.message("python.packaging.progress.text.installing.specific.package", requirement.presentableText) updateProgress(indicator, index, requirements.size) - val specification = createSpecificationForRequirement(requirement) - packageService.installPackage(specification, extraArgs) + // FIXME: pass version??? + val specification = PythonSimplePackageSpecification(requirement.name, null, null) + manager.installPackage(specification, extraArgs).onFailure { + return Result.failure(it) + } } + + return Result.success(Unit) } private fun updateProgress(indicator: ProgressIndicator, index: Int, total: Int) { @@ -65,12 +80,5 @@ class PythonPackagesInstallerAsync { indicator.fraction = index.toDouble() / total } } - - private fun createSpecificationForRequirement( - requirement: PyRequirement, - ): PythonPackageSpecification { - val packageName = requirement.name - return PythonSimplePackageSpecification(packageName, null, null) - } } }