mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
PY-49271 Packages(feat): Provide an ability to pass arbitrary options to pip install
GitOrigin-RevId: 29a1f81fd5cb17923385b478c19864957c87cebf
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c3d76fcc00
commit
39ac2bc2ae
@@ -864,6 +864,7 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
|
||||
<actions resource-bundle="messages.PyBundle">
|
||||
<group id="PyPackageToolwindowContext">
|
||||
<action id="PyInstallPackage" class="com.jetbrains.python.packaging.toolwindow.actions.InstallPackageAction"/>
|
||||
<action id="PyInstallWithOptionPackage" class="com.jetbrains.python.packaging.toolwindow.actions.InstallWithOptionsPackageAction"/>
|
||||
<action id="PyDeletePackage" class="com.jetbrains.python.packaging.toolwindow.actions.DeletePackageAction"/>
|
||||
<action id="PyChangeVersionPackage" class="com.jetbrains.python.packaging.toolwindow.actions.ChangeVersionPackageAction"/>
|
||||
<action id="PyUpdateToLatestPackage" class="com.jetbrains.python.packaging.toolwindow.actions.UpdatePackageToLatestAction"/>
|
||||
|
||||
@@ -118,10 +118,10 @@ class CondaPackageManager(project: Project, sdk: Sdk) : PipBasedPackageManager(p
|
||||
val commandLineString = StringUtil.join(commandLine, " ")
|
||||
val handler = CapturingProcessHandler(process, targetedCommandLine.charset, commandLineString)
|
||||
|
||||
val result = withBackgroundProgress<Unit>(project, text, true) {
|
||||
val result = withBackgroundProgress(project, text, true) {
|
||||
withRawProgressReporter<ProcessOutput?> {
|
||||
handler.runProcess(10 * 60 * 1000)
|
||||
}
|
||||
} as ProcessOutput
|
||||
}
|
||||
|
||||
result.checkSuccess(thisLogger())
|
||||
@@ -133,5 +133,4 @@ class CondaPackageManager(project: Project, sdk: Sdk) : PipBasedPackageManager(p
|
||||
else result.stdout
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,8 +67,10 @@ class PyPackagingTablesView(private val project: Project,
|
||||
if (existingRepo != null) {
|
||||
// recreate order of the repositories -- it might have changed in the package manager (e.g. Sdk switch)
|
||||
existingRepo.removeFrom(container)
|
||||
val selectedItem = existingRepo.table.selectedItem()
|
||||
existingRepo.items = withExpander
|
||||
existingRepo.addTo(container)
|
||||
selectedItem?.let { existingRepo.table.selectPackage(it) }
|
||||
}
|
||||
else {
|
||||
val newTable = PyPackagesTable(project, PyPackagesTableModel(), this, controller)
|
||||
|
||||
@@ -140,6 +140,8 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo
|
||||
super.uiDataSnapshot(sink)
|
||||
}
|
||||
|
||||
fun getSelectedPackage(): DisplayablePackage? = descriptionController.selectedPackage.get()
|
||||
|
||||
private fun initOrientation(service: PyPackagingToolWindowService, horizontal: Boolean) {
|
||||
val second = if (splitter?.secondComponent == rightPanel) rightPanel else noPackagePanel
|
||||
val proportionKey = if (horizontal) HORIZONTAL_SPLITTER_KEY else VERTICAL_SPLITTER_KEY
|
||||
|
||||
@@ -38,8 +38,7 @@ import org.jetbrains.annotations.Nls
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
class PyPackagingToolWindowService(val project: Project, val serviceScope: CoroutineScope) : Disposable {
|
||||
var toolWindowPanel: PyPackagingToolWindowPanel? = null
|
||||
private set
|
||||
private var toolWindowPanel: PyPackagingToolWindowPanel? = null
|
||||
lateinit var manager: PythonPackageManager
|
||||
private var installedPackages: Map<String, InstalledPackage> = emptyMap()
|
||||
internal var currentSdk: Sdk? = null
|
||||
@@ -67,6 +66,8 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
|
||||
|
||||
|
||||
fun handleSearch(query: String) {
|
||||
val prevSelected = toolWindowPanel?.getSelectedPackage()
|
||||
|
||||
currentQuery = query
|
||||
if (query.isNotEmpty()) {
|
||||
searchJob?.cancel()
|
||||
@@ -85,6 +86,7 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
|
||||
if (isActive) {
|
||||
withContext(Dispatchers.Main) {
|
||||
toolWindowPanel?.showSearchResult(installed, packagesFromRepos + invalidRepositories)
|
||||
prevSelected?.name?.let { toolWindowPanel?.selectPackageName(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,26 +98,24 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou
|
||||
}.toList()
|
||||
|
||||
toolWindowPanel?.resetSearch(installedPackages.values.toList(), packagesByRepository + invalidRepositories)
|
||||
prevSelected?.name?.let { toolWindowPanel?.selectPackageName(it) }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun installPackage(specification: PythonPackageSpecification, options: List<String> = emptyList()) {
|
||||
PythonPackagesToolwindowStatisticsCollector.installPackageEvent.log(project)
|
||||
val result = manager.installPackage(specification, options = options)
|
||||
toolWindowPanel?.selectPackageName(specification.name)
|
||||
if (result.isSuccess) showPackagingNotification(message("python.packaging.notification.installed", specification.name))
|
||||
}
|
||||
|
||||
suspend fun deletePackage(selectedPackage: InstalledPackage) {
|
||||
PythonPackagesToolwindowStatisticsCollector.uninstallPackageEvent.log(project)
|
||||
val result = manager.uninstallPackage(selectedPackage.instance)
|
||||
toolWindowPanel?.selectPackageName(selectedPackage.name)
|
||||
if (result.isSuccess) showPackagingNotification(message("python.packaging.notification.deleted", selectedPackage.name))
|
||||
}
|
||||
|
||||
suspend fun updatePackage(specification: PythonPackageSpecification) {
|
||||
val result = manager.updatePackage(specification)
|
||||
toolWindowPanel?.selectPackageName(specification.name)
|
||||
if (result.isSuccess) showPackagingNotification(message("python.packaging.notification.updated", specification.name, specification.versionSpecs))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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.toolwindow.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents.selectedPackage
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class InstallWithOptionsPackageAction : DumbAwareAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val pkg = e.selectedPackage as? InstallablePackage ?: return
|
||||
|
||||
|
||||
PyPackageCoroutine.launch(project, Dispatchers.IO) {
|
||||
val service = PyPackagingToolWindowService.getInstance(project)
|
||||
val details = service.detailsForPackage(pkg)
|
||||
|
||||
installWithOptions(project, details)
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = e.selectedPackage is InstallablePackage
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
||||
|
||||
companion object {
|
||||
internal suspend fun installWithOptions(project: Project, details: PythonPackageDetails, version: String? = null) {
|
||||
val optionsString = withContext(Dispatchers.EDT) {
|
||||
Messages.showInputDialog(project,
|
||||
message("package.install.with.options.dialog.message"),
|
||||
message("action.PyInstallWithOptionPackage.text"),
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
} ?: return
|
||||
|
||||
val options = optionsString.split(' ').map { it.trim() }.filter { it.isNotBlank() }
|
||||
|
||||
val specification = details.repository.createPackageSpecification(details.name, version ?: details.availableVersions.first())
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification, options)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.ide.plugins.newui.OneLineProgressIndicator
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.UiDataProvider
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.observable.properties.AtomicBooleanProperty
|
||||
import com.intellij.openapi.observable.properties.AtomicProperty
|
||||
@@ -15,7 +14,6 @@ import com.intellij.openapi.observable.util.isNotNull
|
||||
import com.intellij.openapi.observable.util.not
|
||||
import com.intellij.openapi.observable.util.transform
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
@@ -32,6 +30,7 @@ import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.PyPackageUtil
|
||||
import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.InstallWithOptionsPackageAction
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstalledPackage
|
||||
@@ -39,7 +38,6 @@ import com.jetbrains.python.packaging.toolwindow.ui.PyPackagesUiComponents
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Font
|
||||
@@ -75,19 +73,8 @@ class PyPackageDescriptionController(val project: Project) : Disposable {
|
||||
|
||||
private val installWithOptionAction: Action = wrapAction(message("action.PyInstallWithOptionPackage.text"), message("progress.text.installing")) {
|
||||
val details = selectedPackageDetails.get() ?: return@wrapAction
|
||||
|
||||
val optionsString = withContext(Dispatchers.EDT) {
|
||||
Messages.showInputDialog(project,
|
||||
message("package.install.with.options.dialog.message"),
|
||||
message("action.PyInstallWithOptionPackage.text"),
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
} ?: return@wrapAction
|
||||
|
||||
val options = optionsString.split(' ').map { it.trim() }.filter { it.isNotBlank() }
|
||||
|
||||
val specification = details.repository.createPackageSpecification(details.name, details.availableVersions.first())
|
||||
project.service<PyPackagingToolWindowService>().installPackage(specification, options)
|
||||
val version = versionSelector.text.takeIf { it != latestText }
|
||||
InstallWithOptionsPackageAction.installWithOptions(project, details,version)
|
||||
}
|
||||
|
||||
|
||||
@@ -96,13 +83,6 @@ class PyPackageDescriptionController(val project: Project) : Disposable {
|
||||
private val progressEnabledProperty = AtomicBooleanProperty(false)
|
||||
|
||||
private val progressIndicatorComponent = JPanel()
|
||||
//private val progressBar: JProgressBar = JProgressBar(JProgressBar.HORIZONTAL).apply {
|
||||
// maximumSize.width = 200
|
||||
// minimumSize.width = 200
|
||||
// preferredSize.width = 200
|
||||
// isVisible = false
|
||||
// isIndeterminate = true
|
||||
//}
|
||||
|
||||
private val htmlPanel: JCEFHtmlPanel = PyPackagingJcefHtmlPanel(project).also { panel ->
|
||||
Disposer.register(this, panel)
|
||||
@@ -214,7 +194,10 @@ class PyPackageDescriptionController(val project: Project) : Disposable {
|
||||
private fun suggestInstallPackage(selectedValue: String) {
|
||||
if (selectedPackage.get() !is InstalledPackage)
|
||||
return
|
||||
updatePackageVersion(selectedValue)
|
||||
|
||||
wrapInvokeOp(message("progress.text.installing")) {
|
||||
updatePackageVersion(selectedValue)
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateVersionText() = (selectedPackage.get() as? InstalledPackage)?.currentVersion?.presentableText ?: latestText
|
||||
|
||||
Reference in New Issue
Block a user