mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
extract common code for listing installed/outdated packages for poetry; #PY-78077 Fixed
GitOrigin-RevId: ba1410bab2aeb4b69e6a9b134fd81331b7de3b06
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b21ed9e4e9
commit
3f017485ef
@@ -16,8 +16,12 @@ import com.intellij.openapi.util.io.FileUtil
|
|||||||
import com.intellij.platform.ide.progress.withBackgroundProgress
|
import com.intellij.platform.ide.progress.withBackgroundProgress
|
||||||
import com.intellij.util.SystemProperties
|
import com.intellij.util.SystemProperties
|
||||||
import com.jetbrains.python.PyBundle
|
import com.jetbrains.python.PyBundle
|
||||||
|
import com.jetbrains.python.packaging.PyPackage
|
||||||
import com.jetbrains.python.packaging.PyExecutionException
|
import com.jetbrains.python.packaging.PyExecutionException
|
||||||
import com.jetbrains.python.packaging.PyPackageManager
|
import com.jetbrains.python.packaging.PyPackageManager
|
||||||
|
import com.jetbrains.python.packaging.PyRequirement
|
||||||
|
import com.jetbrains.python.packaging.PyRequirementParser
|
||||||
|
import com.jetbrains.python.packaging.common.PythonOutdatedPackage
|
||||||
import com.jetbrains.python.packaging.common.PythonPackage
|
import com.jetbrains.python.packaging.common.PythonPackage
|
||||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||||
import com.jetbrains.python.pathValidation.PlatformAndRoot
|
import com.jetbrains.python.pathValidation.PlatformAndRoot
|
||||||
@@ -198,7 +202,7 @@ fun parsePoetryShow(input: String): List<PythonPackage> {
|
|||||||
val result = mutableListOf<PythonPackage>()
|
val result = mutableListOf<PythonPackage>()
|
||||||
input.split("\n").forEach { line ->
|
input.split("\n").forEach { line ->
|
||||||
if (line.isNotBlank()) {
|
if (line.isNotBlank()) {
|
||||||
val packageInfo = line.trim().split(" ").map { it.trim() }.filter { it.isNotBlank() && it != "(!)"}
|
val packageInfo = line.trim().split(" ").map { it.trim() }.filter { it.isNotBlank() && it != "(!)" }
|
||||||
result.add(PythonPackage(packageInfo[0], packageInfo[1], false))
|
result.add(PythonPackage(packageInfo[0], packageInfo[1], false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,6 +210,70 @@ fun parsePoetryShow(input: String): List<PythonPackage> {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
suspend fun poetryShowOutdated(sdk: Sdk): Result<Map<String, PythonOutdatedPackage>> {
|
||||||
|
val output = runPoetryWithSdk(sdk, "show", "--outdated").getOrElse {
|
||||||
|
return Result.failure(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsePoetryShowOutdated(output).let { Result.success(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
suspend fun poetryListPackages(sdk: Sdk): Result<Pair<List<PyPackage>, List<PyRequirement>>> {
|
||||||
|
// Just in case there were any changes to pyproject.toml
|
||||||
|
if (runPoetryWithSdk(sdk, "lock", "--check").isFailure) {
|
||||||
|
runPoetryWithSdk(sdk, "lock", "--no-update")
|
||||||
|
}
|
||||||
|
|
||||||
|
val output = runPoetryWithSdk(sdk, "install", "--dry-run", "--no-root").getOrElse {
|
||||||
|
return Result.failure(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsePoetryInstallDryRun(output).let {
|
||||||
|
Result.success(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
fun parsePoetryInstallDryRun(input: String): Pair<List<PyPackage>, List<PyRequirement>> {
|
||||||
|
val installedLines = listOf("Already installed", "Skipping", "Updating")
|
||||||
|
|
||||||
|
fun getNameAndVersion(line: String): Triple<String, String, String> {
|
||||||
|
return line.split(" ").let {
|
||||||
|
val installedVersion = it[5].replace(Regex("[():]"), "")
|
||||||
|
val requiredVersion = when {
|
||||||
|
it.size > 7 && it[6] == "->" -> it[7].replace(Regex("[():]"), "")
|
||||||
|
else -> installedVersion
|
||||||
|
}
|
||||||
|
Triple(it[4], installedVersion, requiredVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVersion(version: String): String {
|
||||||
|
return if (Regex("^[0-9]").containsMatchIn(version)) "==$version" else version
|
||||||
|
}
|
||||||
|
|
||||||
|
val pyPackages = mutableListOf<PyPackage>()
|
||||||
|
val pyRequirements = mutableListOf<PyRequirement>()
|
||||||
|
input
|
||||||
|
.lineSequence()
|
||||||
|
.filter { listOf(")", "Already installed").any { lastWords -> it.endsWith(lastWords) } }
|
||||||
|
.forEach { line ->
|
||||||
|
getNameAndVersion(line).also {
|
||||||
|
if (installedLines.any { installedLine -> line.contains(installedLine) }) {
|
||||||
|
pyPackages.add(PyPackage(it.first, it.second, null, emptyList()))
|
||||||
|
PyRequirementParser.fromLine(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }
|
||||||
|
}
|
||||||
|
else if (line.contains("Installing")) {
|
||||||
|
PyRequirementParser.fromLine(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair(pyPackages.distinct().toList(), pyRequirements.distinct().toList())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the Poetry environment for the specified module path with the given arguments.
|
* Configures the Poetry environment for the specified module path with the given arguments.
|
||||||
* Runs command: GeneralCommandLine("poetry config [args]").withWorkingDirectory([modulePath])
|
* Runs command: GeneralCommandLine("poetry config [args]").withWorkingDirectory([modulePath])
|
||||||
|
|||||||
@@ -27,29 +27,23 @@ class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pr
|
|||||||
override suspend fun uninstallPackageCommand(pkg: PythonPackage): Result<String> = poetryUninstallPackage(sdk, pkg.name)
|
override suspend fun uninstallPackageCommand(pkg: PythonPackage): Result<String> = poetryUninstallPackage(sdk, pkg.name)
|
||||||
|
|
||||||
override suspend fun reloadPackagesCommand(): Result<List<PythonPackage>> {
|
override suspend fun reloadPackagesCommand(): Result<List<PythonPackage>> {
|
||||||
return poetryShowPackages(sdk)
|
val (installed, _) = poetryListPackages(sdk).getOrElse {
|
||||||
}
|
return Result.failure(it)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun reloadPackages(): Result<List<PythonPackage>> {
|
outdatedPackages = poetryShowOutdated(sdk).getOrElse {
|
||||||
updateOutdatedPackages()
|
emptyMap()
|
||||||
return super.reloadPackages()
|
}
|
||||||
|
|
||||||
|
val packages = installed.map {
|
||||||
|
PythonPackage(it.name, it.version, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.success(packages)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getOutdatedPackages(): Map<String, PythonOutdatedPackage> = outdatedPackages
|
internal fun getOutdatedPackages(): Map<String, PythonOutdatedPackage> = outdatedPackages
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the list of outdated packages by running the Poetry command
|
|
||||||
* `poetry show --outdated`, parsing its output, and storing the results.
|
|
||||||
*/
|
|
||||||
private suspend fun updateOutdatedPackages() {
|
|
||||||
val outputOutdatedPackages = runPoetryWithSdk(sdk, "show", "--outdated").getOrElse {
|
|
||||||
outdatedPackages = emptyMap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
outdatedPackages = parsePoetryShowOutdated(outputOutdatedPackages)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PythonPackageSpecification.getVersionForPoetry(): String = if (versionSpecs == null) name else "$name@$versionSpecs"
|
private fun PythonPackageSpecification.getVersionForPoetry(): String = if (versionSpecs == null) name else "$name@$versionSpecs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import com.jetbrains.python.sdk.associatedModuleDir
|
|||||||
|
|
||||||
|
|
||||||
class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
||||||
private val installedLines = listOf("Already installed", "Skipping", "Updating")
|
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var packages: List<PyPackage>? = null
|
private var packages: List<PyPackage>? = null
|
||||||
|
|
||||||
@@ -37,13 +35,13 @@ class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
|||||||
override fun install(requirements: List<PyRequirement>?, extraArgs: List<String>) {
|
override fun install(requirements: List<PyRequirement>?, extraArgs: List<String>) {
|
||||||
val args = if (requirements.isNullOrEmpty()) {
|
val args = if (requirements.isNullOrEmpty()) {
|
||||||
listOfNotNull(listOf("install"),
|
listOfNotNull(listOf("install"),
|
||||||
extraArgs)
|
extraArgs)
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
listOfNotNull(listOf("add"),
|
listOfNotNull(listOf("add"),
|
||||||
requirements.map { it.name },
|
requirements.map { it.name },
|
||||||
extraArgs)
|
extraArgs)
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,29 +85,27 @@ class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
|||||||
|
|
||||||
override fun getPackages() = packages
|
override fun getPackages() = packages
|
||||||
|
|
||||||
fun getOutdatedPackages() = outdatedPackages
|
|
||||||
|
|
||||||
override fun refreshAndGetPackages(alwaysRefresh: Boolean): List<PyPackage> {
|
override fun refreshAndGetPackages(alwaysRefresh: Boolean): List<PyPackage> {
|
||||||
if (alwaysRefresh || packages == null) {
|
if (alwaysRefresh || packages == null) {
|
||||||
packages = null
|
val allPackages = runBlockingCancellable {
|
||||||
val outputInstallDryRun = runBlockingCancellable { runPoetryWithSdk(sdk, "install", "--dry-run", "--no-root") }.getOrElse {
|
poetryListPackages(sdk)
|
||||||
|
}.getOrElse {
|
||||||
packages = emptyList()
|
packages = emptyList()
|
||||||
return packages ?: emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val allPackage = parsePoetryInstallDryRun(outputInstallDryRun)
|
packages = allPackages.first
|
||||||
packages = allPackage.first
|
requirements = allPackages.second
|
||||||
requirements = allPackage.second
|
|
||||||
|
|
||||||
val outputOutdatedPackages = runBlockingCancellable { runPoetryWithSdk(sdk, "show", "--outdated") }.getOrElse {
|
runBlockingCancellable {
|
||||||
outdatedPackages = emptyMap()
|
outdatedPackages = poetryShowOutdated(sdk).getOrElse {
|
||||||
|
emptyMap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputOutdatedPackages is String) {
|
|
||||||
outdatedPackages = parsePoetryShowOutdated(outputOutdatedPackages)
|
|
||||||
}
|
|
||||||
ApplicationManager.getApplication().messageBus.syncPublisher(PACKAGE_MANAGER_TOPIC).packagesRefreshed(sdk)
|
ApplicationManager.getApplication().messageBus.syncPublisher(PACKAGE_MANAGER_TOPIC).packagesRefreshed(sdk)
|
||||||
}
|
}
|
||||||
|
|
||||||
return packages ?: emptyList()
|
return packages ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,42 +126,4 @@ class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
|||||||
// TODO: Parse the dependency information from `pipenv graph`
|
// TODO: Parse the dependency information from `pipenv graph`
|
||||||
return emptySet()
|
return emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getVersion(version: String): String {
|
|
||||||
return if (Regex("^[0-9]").containsMatchIn(version)) "==$version" else version
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the output of `poetry install --dry-run ` into a list of packages.
|
|
||||||
*/
|
|
||||||
private fun parsePoetryInstallDryRun(input: String): Pair<List<PyPackage>, List<PyRequirement>> {
|
|
||||||
fun getNameAndVersion(line: String): Triple<String, String, String> {
|
|
||||||
return line.split(" ").let {
|
|
||||||
val installedVersion = it[5].replace(Regex("[():]"), "")
|
|
||||||
val requiredVersion = when {
|
|
||||||
it.size > 7 && it[6] == "->" -> it[7].replace(Regex("[():]"), "")
|
|
||||||
else -> installedVersion
|
|
||||||
}
|
|
||||||
Triple(it[4], installedVersion, requiredVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val pyPackages = mutableListOf<PyPackage>()
|
|
||||||
val pyRequirements = mutableListOf<PyRequirement>()
|
|
||||||
input
|
|
||||||
.lineSequence()
|
|
||||||
.filter { listOf(")", "Already installed").any { lastWords -> it.endsWith(lastWords) } }
|
|
||||||
.forEach { line ->
|
|
||||||
getNameAndVersion(line).also {
|
|
||||||
if (installedLines.any { installedLine -> line.contains(installedLine) }) {
|
|
||||||
pyPackages.add(PyPackage(it.first, it.second, null, emptyList()))
|
|
||||||
this.parseRequirement(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }
|
|
||||||
}
|
|
||||||
else if (line.contains("Installing")) {
|
|
||||||
this.parseRequirement(it.first + getVersion(it.third))?.let { pyRequirement -> pyRequirements.add(pyRequirement) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Pair(pyPackages.distinct().toList(), pyRequirements.distinct().toList())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user