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.util.SystemProperties
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.PyPackage
|
||||
import com.jetbrains.python.packaging.PyExecutionException
|
||||
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.management.PythonPackageManager
|
||||
import com.jetbrains.python.pathValidation.PlatformAndRoot
|
||||
@@ -206,6 +210,70 @@ fun parsePoetryShow(input: String): List<PythonPackage> {
|
||||
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.
|
||||
* 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 reloadPackagesCommand(): Result<List<PythonPackage>> {
|
||||
return poetryShowPackages(sdk)
|
||||
val (installed, _) = poetryListPackages(sdk).getOrElse {
|
||||
return Result.failure(it)
|
||||
}
|
||||
|
||||
override suspend fun reloadPackages(): Result<List<PythonPackage>> {
|
||||
updateOutdatedPackages()
|
||||
return super.reloadPackages()
|
||||
outdatedPackages = poetryShowOutdated(sdk).getOrElse {
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
val packages = installed.map {
|
||||
PythonPackage(it.name, it.version, false)
|
||||
}
|
||||
|
||||
return Result.success(packages)
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ import com.jetbrains.python.sdk.associatedModuleDir
|
||||
|
||||
|
||||
class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
||||
private val installedLines = listOf("Already installed", "Skipping", "Updating")
|
||||
|
||||
@Volatile
|
||||
private var packages: List<PyPackage>? = null
|
||||
|
||||
@@ -87,29 +85,27 @@ class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
||||
|
||||
override fun getPackages() = packages
|
||||
|
||||
fun getOutdatedPackages() = outdatedPackages
|
||||
|
||||
override fun refreshAndGetPackages(alwaysRefresh: Boolean): List<PyPackage> {
|
||||
if (alwaysRefresh || packages == null) {
|
||||
packages = null
|
||||
val outputInstallDryRun = runBlockingCancellable { runPoetryWithSdk(sdk, "install", "--dry-run", "--no-root") }.getOrElse {
|
||||
val allPackages = runBlockingCancellable {
|
||||
poetryListPackages(sdk)
|
||||
}.getOrElse {
|
||||
packages = emptyList()
|
||||
return packages ?: emptyList()
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val allPackage = parsePoetryInstallDryRun(outputInstallDryRun)
|
||||
packages = allPackage.first
|
||||
requirements = allPackage.second
|
||||
packages = allPackages.first
|
||||
requirements = allPackages.second
|
||||
|
||||
val outputOutdatedPackages = runBlockingCancellable { runPoetryWithSdk(sdk, "show", "--outdated") }.getOrElse {
|
||||
outdatedPackages = emptyMap()
|
||||
runBlockingCancellable {
|
||||
outdatedPackages = poetryShowOutdated(sdk).getOrElse {
|
||||
emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
if (outputOutdatedPackages is String) {
|
||||
outdatedPackages = parsePoetryShowOutdated(outputOutdatedPackages)
|
||||
}
|
||||
ApplicationManager.getApplication().messageBus.syncPublisher(PACKAGE_MANAGER_TOPIC).packagesRefreshed(sdk)
|
||||
}
|
||||
|
||||
return packages ?: emptyList()
|
||||
}
|
||||
|
||||
@@ -130,42 +126,4 @@ class PyPoetryPackageManager(sdk: Sdk) : PyPackageManager(sdk) {
|
||||
// TODO: Parse the dependency information from `pipenv graph`
|
||||
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