From a818550514a35bc7ee607b6ae06da6006a599df1 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 10 Aug 2020 02:44:46 +0900 Subject: [PATCH 1/2] add a version inspection --- resources/META-INF/only-toml.xml | 1 + .../poetry/PoetryVersionInspection.kt | 47 +++++++++++++++++++ .../koxudaxi/poetry/PyPoetryPackageManager.kt | 18 ++++++- src/com/koxudaxi/poetry/poetry.kt | 19 +++++++- .../parsePoetryShoOutdated/show-outdated.txt | 5 ++ testSrc/com/koxudaxi/poetry/PoetryTest.kt | 22 ++++++++- 6 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 src/com/koxudaxi/poetry/PoetryVersionInspection.kt create mode 100644 testData/Poetry/parsePoetryShoOutdated/show-outdated.txt diff --git a/resources/META-INF/only-toml.xml b/resources/META-INF/only-toml.xml index e1bc25a..64b43b0 100644 --- a/resources/META-INF/only-toml.xml +++ b/resources/META-INF/only-toml.xml @@ -4,6 +4,7 @@ implementationClass="com.koxudaxi.poetry.PoetryExtrasLineMarkerContributor"/> + \ No newline at end of file diff --git a/src/com/koxudaxi/poetry/PoetryVersionInspection.kt b/src/com/koxudaxi/poetry/PoetryVersionInspection.kt new file mode 100644 index 0000000..f3df41a --- /dev/null +++ b/src/com/koxudaxi/poetry/PoetryVersionInspection.kt @@ -0,0 +1,47 @@ +package com.koxudaxi.poetry + +import com.intellij.codeInspection.* +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.module.ModuleUtilCore +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiElementVisitor +import com.intellij.psi.PsiFile +import com.jetbrains.python.sdk.* +import org.toml.lang.psi.* + +class PoetryVersionInspection : LocalInspectionTool() { + override fun buildVisitor(holder: ProblemsHolder, + isOnTheFly: Boolean, + session: LocalInspectionToolSession): PsiElementVisitor { + return PoetryFileVisitor(holder, session) + } + + class PoetryFileVisitor(val holder: ProblemsHolder, + session: LocalInspectionToolSession) : PsiElementVisitor() { + private fun guessModule(element: PsiElement): Module? { + return ModuleUtilCore.findModuleForPsiElement(element) + ?: ModuleManager.getInstance(element.project).modules.let { if (it.size != 1) null else it[0] } + } + + override fun visitFile(file: PsiFile) { + val module = guessModule(file) ?: return + val sdk = PythonSdkUtil.findPythonSdk(module) ?: return + if (!isPoetry(file.project, sdk)) return + if (file.virtualFile != module.pyProjectToml) return + file.children + .filter { element -> + (element as? TomlTable)?.header?.names?.joinToString(".") { it.text } in listOf("tool.poetry.dependencies", "tool.poetry.dev-dependencies") + }.flatMap { + it.children.mapNotNull { line -> line as? TomlKeyValue } + }.forEach { keyValue -> + val packageName = keyValue.key.text + val outdatedVersion = PyPoetryPackageManager.getInstance(sdk).getOutdatedPackages()[packageName] + if (outdatedVersion is PoetryOutdatedVersion) { + val message = "'${packageName}' version ${outdatedVersion.currentVersion} is outdated (latest: ${outdatedVersion.latestVersion})" + holder.registerProblem(keyValue, message, ProblemHighlightType.WARNING) + } + } + } + } +} diff --git a/src/com/koxudaxi/poetry/PyPoetryPackageManager.kt b/src/com/koxudaxi/poetry/PyPoetryPackageManager.kt index 76665b4..6eab6c2 100644 --- a/src/com/koxudaxi/poetry/PyPoetryPackageManager.kt +++ b/src/com/koxudaxi/poetry/PyPoetryPackageManager.kt @@ -28,6 +28,8 @@ class PyPoetryPackageManager(val sdk: Sdk) : PyPackageManager() { private var requirements: List? = null + private var outdatedPackages: Map = emptyMap() + init { PyPackageUtil.runOnChangeUnderInterpreterPaths(sdk) { PythonSdkType.getInstance().setupSdkPaths(sdk) @@ -93,6 +95,8 @@ class PyPoetryPackageManager(val sdk: Sdk) : PyPackageManager() { fun getRequirements() = requirements + fun getOutdatedPackages() = outdatedPackages + override fun refreshAndGetPackages(alwaysRefresh: Boolean): List { return refreshAndGetPackages(alwaysRefresh, true) } @@ -100,15 +104,25 @@ class PyPoetryPackageManager(val sdk: Sdk) : PyPackageManager() { fun refreshAndGetPackages(alwaysRefresh: Boolean, notify: Boolean): List { if (alwaysRefresh || packages == null) { packages = null - val output = try { + val outputInstallDryRun = try { runPoetry(sdk, "install", "--dry-run", "--no-root") } catch (e: ExecutionException) { packages = emptyList() return packages ?: emptyList() } - val allPackage = parsePoetryInstallDryRun(output) + val allPackage = parsePoetryInstallDryRun(outputInstallDryRun) packages = allPackage.first requirements = allPackage.second + + val outputOutdatedPackages = try { + runPoetry(sdk, "show", "--outdated") + } catch (e: ExecutionException) { + outdatedPackages = emptyMap() + } + if (outputOutdatedPackages is String) { + outdatedPackages = parsePoetryShowOutdated(outputOutdatedPackages) + } + if (notify) { ApplicationManager.getApplication().messageBus.syncPublisher(PACKAGE_MANAGER_TOPIC).packagesRefreshed(sdk) } diff --git a/src/com/koxudaxi/poetry/poetry.kt b/src/com/koxudaxi/poetry/poetry.kt index a92b04c..d2215bb 100644 --- a/src/com/koxudaxi/poetry/poetry.kt +++ b/src/com/koxudaxi/poetry/poetry.kt @@ -60,11 +60,11 @@ import org.apache.tuweni.toml.TomlParseResult import org.apache.tuweni.toml.TomlTable import org.jetbrains.annotations.SystemDependent import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.utils.KotlinPathsFromHomeDir import org.jetbrains.kotlin.utils.getOrPutNullable import java.io.File import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException +import java.util.regex.Pattern const val PY_PROJECT_TOML: String = "pyproject.toml" const val POETRY_LOCK: String = "poetry.lock" @@ -635,3 +635,20 @@ inline fun syncRunPoetry(projectPath: @SystemDependent String, varar fun getPythonExecutable(homePath: String): String = PythonSdkUtil.getPythonExecutable(homePath) ?: FileUtil.join(homePath, "bin", "python") + +/** + * Parses the output of `poetry show --outdated` into a list of packages. + */ +fun parsePoetryShowOutdated(input: String): Map { + return input + .lines() + .mapNotNull { line -> + line.split(Pattern.compile(" +")) + .takeIf { it.size > 3 }?.let { it[0] to PoetryOutdatedVersion(it[1], it[2]) } + }.toMap() +} + + +data class PoetryOutdatedVersion( + @SerializedName("currentVersion") var currentVersion: String, + @SerializedName("latestVersion") var latestVersion: String) \ No newline at end of file diff --git a/testData/Poetry/parsePoetryShoOutdated/show-outdated.txt b/testData/Poetry/parsePoetryShoOutdated/show-outdated.txt new file mode 100644 index 0000000..ade2834 --- /dev/null +++ b/testData/Poetry/parsePoetryShoOutdated/show-outdated.txt @@ -0,0 +1,5 @@ +boto3 1.13.26 1.14.38 The AWS SDK for Python +botocore 1.16.26 1.17.38 Low-level, data-driven core of boto 3. +docutils 0.15.2 0.16 Docutils -- Python Documentation Utilities +pydantic 1.4 1.6.1 Data validation and settings management using python 3.6 type hinting + diff --git a/testSrc/com/koxudaxi/poetry/PoetryTest.kt b/testSrc/com/koxudaxi/poetry/PoetryTest.kt index d9f97e7..8e9bb63 100644 --- a/testSrc/com/koxudaxi/poetry/PoetryTest.kt +++ b/testSrc/com/koxudaxi/poetry/PoetryTest.kt @@ -2,8 +2,6 @@ package com.koxudaxi.poetry import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl -import org.jetbrains.kotlin.konan.file.File class PoetryTest : PoetryTestCase() { @@ -11,6 +9,7 @@ class PoetryTest : PoetryTestCase() { get() { return getTestData("pyproject.toml") } + fun testGetPyProjectTomlForPoetry() { val result = getPyProjectTomlForPoetry(testFile) assertEquals(result.first, 0) @@ -28,4 +27,23 @@ class PoetryTest : PoetryTestCase() { assertEquals(result.first, 0) assertEquals(result.second, null) } + + private val testShowOutdatedDataAsText: String + get() { + return getTestDataAsText("show-outdated.txt") + } + + fun testParsePoetryShoOutdated() { + val result = parsePoetryShowOutdated(testShowOutdatedDataAsText) + assertEquals(result.size, 4) + assertEquals(result, + mapOf( + "boto3" to PoetryOutdatedVersion(currentVersion = "1.13.26", latestVersion = "1.14.38"), + "botocore" to PoetryOutdatedVersion(currentVersion = "1.16.26", latestVersion = "1.17.38"), + "docutils" to PoetryOutdatedVersion(currentVersion = "0.15.2", latestVersion = "0.16"), + "pydantic" to PoetryOutdatedVersion(currentVersion = "1.4", latestVersion = "1.6.1") + ) + ) + } + } \ No newline at end of file From c5d87f9370cbf6432b98571df6e49c5e74c5dbbf Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 10 Aug 2020 23:19:37 +0900 Subject: [PATCH 2/2] update documents --- README.md | 2 +- docs/index.md | 1 + resources/META-INF/only-toml.xml | 2 +- resources/META-INF/plugin.xml | 7 ++++++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 370fc76..09ba64a 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ You can install the stable version on PyCharm's `Marketplace` (Preference -> Plu - update and lock with a popup - show a message and a link to fix settings (QuickFix) - install extras and run scripts by clicking a line marker ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required) - +- show a message for outdated version packages ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required) ## Workaround If the plugin does not detect your poetry environment after changing the environment, then please re-open the project. diff --git a/docs/index.md b/docs/index.md index f9ca6fd..8f6a7b2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -39,6 +39,7 @@ You can install the stable version on PyCharm's `Marketplace` (Preference -> Plu - update and lock with a popup - show a message and a link to fix settings (QuickFix) - install extras and run scripts by clicking a line marker ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required) +- show a message for outdated version packages ([Toml plugin](https://plugins.jetbrains.com/plugin/8195-toml) is required) ## Workaround diff --git a/resources/META-INF/only-toml.xml b/resources/META-INF/only-toml.xml index 64b43b0..2888e6e 100644 --- a/resources/META-INF/only-toml.xml +++ b/resources/META-INF/only-toml.xml @@ -4,7 +4,7 @@ implementationClass="com.koxudaxi.poetry.PoetryExtrasLineMarkerContributor"/> - + \ No newline at end of file diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 5331489..5cd30fb 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -1,9 +1,14 @@ com.koxudaxi.poetry Poetry - 0.1.1 + 0.1.2 Koudai Aono @koxudaxi version 0.1.2 +

Features

+
    +
  • Add a version inspection [#85]
  • +

version 0.1.1

Features