From 32fd9f703a495a7209c16a78ee21cfc9e7ed6607 Mon Sep 17 00:00:00 2001 From: khbminus Date: Wed, 21 Dec 2022 14:25:48 +0100 Subject: [PATCH 01/18] Basic implementation of GenerateRequirements TODO: repository lookup, pyproject.toml --- .../io/paddle/plugin/python/PythonPlugin.kt | 7 ++-- .../tasks/resolve/GenerateRequirements.kt | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt index 01373a8a..ac9b95fe 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt @@ -10,9 +10,7 @@ import io.paddle.plugin.python.tasks.install.LockTask import io.paddle.plugin.python.tasks.lint.MyPyTask import io.paddle.plugin.python.tasks.lint.PyLintTask import io.paddle.plugin.python.tasks.publish.TwinePublishTask -import io.paddle.plugin.python.tasks.resolve.ResolveInterpreterTask -import io.paddle.plugin.python.tasks.resolve.ResolveRepositoriesTask -import io.paddle.plugin.python.tasks.resolve.ResolveRequirementsTask +import io.paddle.plugin.python.tasks.resolve.* import io.paddle.plugin.python.tasks.run.RunTask import io.paddle.plugin.python.tasks.test.PyTestTask import io.paddle.plugin.python.tasks.venv.VenvTask @@ -45,7 +43,8 @@ object PythonPlugin : Plugin { MyPyTask(project), PyLintTask(project), WheelTask(project), - TwinePublishTask(project) + TwinePublishTask(project), + GenerateRequirements(project) ) + RunTask.from(project) + PyTestTask.from(project) } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt new file mode 100644 index 00000000..401415a4 --- /dev/null +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt @@ -0,0 +1,34 @@ +package io.paddle.plugin.python.tasks.resolve + +import io.paddle.plugin.python.extensions.requirements +import io.paddle.plugin.python.tasks.PythonPluginTaskGroups +import io.paddle.project.PaddleProject +import io.paddle.tasks.Task +import io.paddle.tasks.incremental.IncrementalTask +import java.io.File + +class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { + override val group: String = PythonPluginTaskGroups.RESOLVE + override val id: String = "requirements" + override val dependencies: List + get() = listOf( + project.tasks.getOrFail("resolveRepositories"), + project.tasks.getOrFail("resolveInterpreter"), + ) + project.subprojects.getAllTasksById(this.id) + + override fun act() { + val requirementsFile = File(project.workDir, REQUIREMENTS_FILE) + .also { it.writeText("") } // Clear file contents + val notResolved = project.requirements.descriptors + notResolved.forEach { descriptor -> + descriptor.versionSpecifier?.clauses?.forEach { version -> + requirementsFile.appendText("${descriptor.name} $version # ${descriptor.type}\n") + } ?: requirementsFile.appendText("${descriptor.name} # ${descriptor.type}\n") + + } + } + + companion object { + private const val REQUIREMENTS_FILE = "requirements.txt" + } +} From a76731b79ebfb339cde4d2c495bf6ff633887e5c Mon Sep 17 00:00:00 2001 From: khbminus Date: Wed, 21 Dec 2022 16:42:21 +0100 Subject: [PATCH 02/18] detached generate into separate task group --- .../src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt | 1 + .../io/paddle/plugin/python/tasks/PythonPluginTaskGroups.kt | 1 + .../tasks/{resolve => generate}/GenerateRequirements.kt | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) rename plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/{resolve => generate}/GenerateRequirements.kt (91%) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt index ac9b95fe..3a5f661e 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt @@ -4,6 +4,7 @@ import io.paddle.plugin.Plugin import io.paddle.plugin.python.dependencies.authentication.AuthenticationProvider import io.paddle.plugin.python.dependencies.index.PyPackageRepositoryIndexer import io.paddle.plugin.python.extensions.* +import io.paddle.plugin.python.tasks.generate.GenerateRequirements import io.paddle.plugin.python.tasks.install.CiTask import io.paddle.plugin.python.tasks.install.InstallTask import io.paddle.plugin.python.tasks.install.LockTask diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/PythonPluginTaskGroups.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/PythonPluginTaskGroups.kt index bf51a763..4dafc4ce 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/PythonPluginTaskGroups.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/PythonPluginTaskGroups.kt @@ -5,4 +5,5 @@ object PythonPluginTaskGroups { const val INSTALL = "install" const val VENV = "venv" const val PUBLISH = "publish" + const val GENERATE = "generate" } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt similarity index 91% rename from plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt rename to plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 401415a4..b80c0795 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/resolve/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,4 +1,4 @@ -package io.paddle.plugin.python.tasks.resolve +package io.paddle.plugin.python.tasks.generate import io.paddle.plugin.python.extensions.requirements import io.paddle.plugin.python.tasks.PythonPluginTaskGroups @@ -8,7 +8,7 @@ import io.paddle.tasks.incremental.IncrementalTask import java.io.File class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { - override val group: String = PythonPluginTaskGroups.RESOLVE + override val group: String = PythonPluginTaskGroups.GENERATE override val id: String = "requirements" override val dependencies: List get() = listOf( From a799f2b81336a13b56174394ad7a6e6f8bb1c453 Mon Sep 17 00:00:00 2001 From: khbminus Date: Wed, 21 Dec 2022 17:06:23 +0100 Subject: [PATCH 03/18] Repository resolving & resolve before file creating --- .../python/tasks/generate/GenerateRequirements.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index b80c0795..d6102862 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,5 +1,6 @@ package io.paddle.plugin.python.tasks.generate +import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository import io.paddle.plugin.python.extensions.requirements import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject @@ -14,17 +15,23 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { get() = listOf( project.tasks.getOrFail("resolveRepositories"), project.tasks.getOrFail("resolveInterpreter"), + project.tasks.getOrFail("resolveInterpreter") ) + project.subprojects.getAllTasksById(this.id) override fun act() { + val notResolved = project.requirements.descriptors + val resolved = project.requirements.resolved val requirementsFile = File(project.workDir, REQUIREMENTS_FILE) .also { it.writeText("") } // Clear file contents - val notResolved = project.requirements.descriptors + notResolved.forEach { descriptor -> + val resolvedPackage = resolved.find { it.name == descriptor.name } + val resolvePath = resolvedPackage?.repo?.let { + if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" + } ?: "" // unresolved package? descriptor.versionSpecifier?.clauses?.forEach { version -> - requirementsFile.appendText("${descriptor.name} $version # ${descriptor.type}\n") - } ?: requirementsFile.appendText("${descriptor.name} # ${descriptor.type}\n") - + requirementsFile.appendText("${descriptor.name}$resolvePath $version # ${descriptor.type}\n") + } ?: requirementsFile.appendText("${descriptor.name}$resolvePath # ${descriptor.type}\n") } } From 5a9d4f9716148061b52717855b62275667e04907 Mon Sep 17 00:00:00 2001 From: khbminus Date: Wed, 21 Dec 2022 18:15:05 +0100 Subject: [PATCH 04/18] Added abstract class to simplify further architecture --- .../tasks/generate/AbstractGenerateTask.kt | 37 +++++++++++++++++++ .../tasks/generate/GenerateRequirements.kt | 31 +++------------- 2 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt new file mode 100644 index 00000000..8fce2fcc --- /dev/null +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt @@ -0,0 +1,37 @@ +package io.paddle.plugin.python.tasks.generate + +import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository +import io.paddle.plugin.python.extensions.requirements +import io.paddle.plugin.python.tasks.PythonPluginTaskGroups +import io.paddle.project.PaddleProject +import io.paddle.tasks.Task +import io.paddle.tasks.incremental.IncrementalTask + +abstract class AbstractGenerateTask(project: PaddleProject) : IncrementalTask(project) { + override val group: String = PythonPluginTaskGroups.GENERATE + override val dependencies: List + get() = listOf( + project.tasks.getOrFail("resolveRepositories"), + project.tasks.getOrFail("resolveInterpreter"), + project.tasks.getOrFail("resolveInterpreter") + ) + project.subprojects.getAllTasksById(this.id) + + override fun act() { + val notResolved = project.requirements.descriptors + val resolved = project.requirements.resolved + val parsedDependencies = buildList { + notResolved.forEach { descriptor -> + val resolvedPackage = resolved.find { it.name == descriptor.name } + val resolvePath = resolvedPackage?.repo?.let { + if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" + } ?: "" // unresolved package? + descriptor.versionSpecifier?.clauses?.forEach { version -> + add("${descriptor.name}$resolvePath $version") + } ?: add("${descriptor.name}$resolvePath") + } + } + processDependencies(parsedDependencies) + } + + abstract fun processDependencies(dependencies: List) +} diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index d6102862..11d2f58c 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,37 +1,18 @@ package io.paddle.plugin.python.tasks.generate -import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository -import io.paddle.plugin.python.extensions.requirements -import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject -import io.paddle.tasks.Task -import io.paddle.tasks.incremental.IncrementalTask import java.io.File -class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { - override val group: String = PythonPluginTaskGroups.GENERATE +class GenerateRequirements(project: PaddleProject) : AbstractGenerateTask(project) { override val id: String = "requirements" - override val dependencies: List - get() = listOf( - project.tasks.getOrFail("resolveRepositories"), - project.tasks.getOrFail("resolveInterpreter"), - project.tasks.getOrFail("resolveInterpreter") - ) + project.subprojects.getAllTasksById(this.id) - override fun act() { - val notResolved = project.requirements.descriptors - val resolved = project.requirements.resolved + override fun processDependencies(dependencies: List) { val requirementsFile = File(project.workDir, REQUIREMENTS_FILE) .also { it.writeText("") } // Clear file contents - - notResolved.forEach { descriptor -> - val resolvedPackage = resolved.find { it.name == descriptor.name } - val resolvePath = resolvedPackage?.repo?.let { - if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" - } ?: "" // unresolved package? - descriptor.versionSpecifier?.clauses?.forEach { version -> - requirementsFile.appendText("${descriptor.name}$resolvePath $version # ${descriptor.type}\n") - } ?: requirementsFile.appendText("${descriptor.name}$resolvePath # ${descriptor.type}\n") + requirementsFile.writeText("") + dependencies.forEach { + requirementsFile.appendText(it) + requirementsFile.appendText("\n") } } From 1804abf3e6db4e1a9fbe0eea9fcc9005fc3b3aff Mon Sep 17 00:00:00 2001 From: khbminus Date: Thu, 22 Dec 2022 00:24:27 +0100 Subject: [PATCH 05/18] TOML generation --- plugins/python/build.gradle.kts | 3 ++ .../io/paddle/plugin/python/PythonPlugin.kt | 4 +- .../tasks/generate/GeneratePyProject.kt | 40 +++++++++++++++++++ .../tasks/generate/GenerateRequirements.kt | 2 +- 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt diff --git a/plugins/python/build.gradle.kts b/plugins/python/build.gradle.kts index b9ad86a8..61d5b177 100644 --- a/plugins/python/build.gradle.kts +++ b/plugins/python/build.gradle.kts @@ -32,6 +32,9 @@ dependencies { implementation("com.github.javakeyring:java-keyring:1.0.1") + implementation("com.akuleshov7:ktoml-core:0.3.0") + implementation("com.akuleshov7:ktoml-file:0.3.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") testImplementation("io.kotest:kotest-runner-junit5:5.4.1") testImplementation("io.kotest:kotest-assertions-core:5.4.1") diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt index 3a5f661e..1636c655 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt @@ -4,6 +4,7 @@ import io.paddle.plugin.Plugin import io.paddle.plugin.python.dependencies.authentication.AuthenticationProvider import io.paddle.plugin.python.dependencies.index.PyPackageRepositoryIndexer import io.paddle.plugin.python.extensions.* +import io.paddle.plugin.python.tasks.generate.GeneratePyProject import io.paddle.plugin.python.tasks.generate.GenerateRequirements import io.paddle.plugin.python.tasks.install.CiTask import io.paddle.plugin.python.tasks.install.InstallTask @@ -45,7 +46,8 @@ object PythonPlugin : Plugin { PyLintTask(project), WheelTask(project), TwinePublishTask(project), - GenerateRequirements(project) + GenerateRequirements(project), + GeneratePyProject(project), ) + RunTask.from(project) + PyTestTask.from(project) } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt new file mode 100644 index 00000000..58e90236 --- /dev/null +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt @@ -0,0 +1,40 @@ +package io.paddle.plugin.python.tasks.generate + +import com.akuleshov7.ktoml.Toml +import io.paddle.plugin.python.extensions.metadata +import io.paddle.project.PaddleProject +import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import java.io.File + +class GeneratePyProject(project: PaddleProject) : AbstractGenerateTask(project) { + override val id: String = "pyProject" + + override fun processDependencies(dependencies: List) { + val pyProjectFile = File(project.workDir, PYPROJECT_FILE) + .also { it.writeText("") } // Clear file contents + pyProjectFile.writeText( + Toml.encodeToString( + PyProjectTOML( + project.id, + project.metadata.version, + project.metadata.description, + dependencies + ) + ) + ) + } + + @Serializable + private data class PyProjectTOML( + val name: String, + val version: String, + val description: String, +// val author: String, // KToml doesn't support inline tables + val dependencies: List + ) + + companion object { + const val PYPROJECT_FILE = "pyproject.toml" + } +} diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 11d2f58c..0bc23f2e 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -17,6 +17,6 @@ class GenerateRequirements(project: PaddleProject) : AbstractGenerateTask(projec } companion object { - private const val REQUIREMENTS_FILE = "requirements.txt" + const val REQUIREMENTS_FILE = "requirements.txt" } } From 6cc5ec6bf305d6fee89b1d729d3f9620408fa524 Mon Sep 17 00:00:00 2001 From: khbminus Date: Fri, 3 Feb 2023 16:43:43 +0100 Subject: [PATCH 06/18] Dropped `toml` support and removed unnecessary abstract class --- .../io/paddle/plugin/python/PythonPlugin.kt | 2 - .../tasks/generate/AbstractGenerateTask.kt | 37 ----------------- .../tasks/generate/GeneratePyProject.kt | 40 ------------------- .../tasks/generate/GenerateRequirements.kt | 32 ++++++++++++++- 4 files changed, 30 insertions(+), 81 deletions(-) delete mode 100644 plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt delete mode 100644 plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt index 1636c655..f465289b 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/PythonPlugin.kt @@ -4,7 +4,6 @@ import io.paddle.plugin.Plugin import io.paddle.plugin.python.dependencies.authentication.AuthenticationProvider import io.paddle.plugin.python.dependencies.index.PyPackageRepositoryIndexer import io.paddle.plugin.python.extensions.* -import io.paddle.plugin.python.tasks.generate.GeneratePyProject import io.paddle.plugin.python.tasks.generate.GenerateRequirements import io.paddle.plugin.python.tasks.install.CiTask import io.paddle.plugin.python.tasks.install.InstallTask @@ -47,7 +46,6 @@ object PythonPlugin : Plugin { WheelTask(project), TwinePublishTask(project), GenerateRequirements(project), - GeneratePyProject(project), ) + RunTask.from(project) + PyTestTask.from(project) } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt deleted file mode 100644 index 8fce2fcc..00000000 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/AbstractGenerateTask.kt +++ /dev/null @@ -1,37 +0,0 @@ -package io.paddle.plugin.python.tasks.generate - -import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository -import io.paddle.plugin.python.extensions.requirements -import io.paddle.plugin.python.tasks.PythonPluginTaskGroups -import io.paddle.project.PaddleProject -import io.paddle.tasks.Task -import io.paddle.tasks.incremental.IncrementalTask - -abstract class AbstractGenerateTask(project: PaddleProject) : IncrementalTask(project) { - override val group: String = PythonPluginTaskGroups.GENERATE - override val dependencies: List - get() = listOf( - project.tasks.getOrFail("resolveRepositories"), - project.tasks.getOrFail("resolveInterpreter"), - project.tasks.getOrFail("resolveInterpreter") - ) + project.subprojects.getAllTasksById(this.id) - - override fun act() { - val notResolved = project.requirements.descriptors - val resolved = project.requirements.resolved - val parsedDependencies = buildList { - notResolved.forEach { descriptor -> - val resolvedPackage = resolved.find { it.name == descriptor.name } - val resolvePath = resolvedPackage?.repo?.let { - if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" - } ?: "" // unresolved package? - descriptor.versionSpecifier?.clauses?.forEach { version -> - add("${descriptor.name}$resolvePath $version") - } ?: add("${descriptor.name}$resolvePath") - } - } - processDependencies(parsedDependencies) - } - - abstract fun processDependencies(dependencies: List) -} diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt deleted file mode 100644 index 58e90236..00000000 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GeneratePyProject.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.paddle.plugin.python.tasks.generate - -import com.akuleshov7.ktoml.Toml -import io.paddle.plugin.python.extensions.metadata -import io.paddle.project.PaddleProject -import kotlinx.serialization.Serializable -import kotlinx.serialization.encodeToString -import java.io.File - -class GeneratePyProject(project: PaddleProject) : AbstractGenerateTask(project) { - override val id: String = "pyProject" - - override fun processDependencies(dependencies: List) { - val pyProjectFile = File(project.workDir, PYPROJECT_FILE) - .also { it.writeText("") } // Clear file contents - pyProjectFile.writeText( - Toml.encodeToString( - PyProjectTOML( - project.id, - project.metadata.version, - project.metadata.description, - dependencies - ) - ) - ) - } - - @Serializable - private data class PyProjectTOML( - val name: String, - val version: String, - val description: String, -// val author: String, // KToml doesn't support inline tables - val dependencies: List - ) - - companion object { - const val PYPROJECT_FILE = "pyproject.toml" - } -} diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 0bc23f2e..6243ab01 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,12 +1,40 @@ package io.paddle.plugin.python.tasks.generate +import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository +import io.paddle.plugin.python.extensions.requirements +import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject +import io.paddle.tasks.Task +import io.paddle.tasks.incremental.IncrementalTask import java.io.File -class GenerateRequirements(project: PaddleProject) : AbstractGenerateTask(project) { +class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { + override val group: String = PythonPluginTaskGroups.GENERATE override val id: String = "requirements" + override val dependencies: List + get() = listOf( + project.tasks.getOrFail("resolveRepositories"), + project.tasks.getOrFail("resolveInterpreter") + ) + project.subprojects.getAllTasksById(this.id) - override fun processDependencies(dependencies: List) { + override fun act() { + val notResolved = project.requirements.descriptors + val resolved = project.requirements.resolved + val parsedDependencies = buildList { + notResolved.forEach { descriptor -> + val resolvedPackage = resolved.find { it.name == descriptor.name } + val resolvePath = resolvedPackage?.repo?.let { + if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" + } ?: "" // unresolved package? + descriptor.versionSpecifier?.clauses?.forEach { version -> + add("${descriptor.name}$resolvePath $version") + } ?: add("${descriptor.name}$resolvePath") + } + } + processDependencies(parsedDependencies) + } + + private fun processDependencies(dependencies: List) { val requirementsFile = File(project.workDir, REQUIREMENTS_FILE) .also { it.writeText("") } // Clear file contents requirementsFile.writeText("") From 13e0bf2b3f5941e076019e5b8c564d4d0bdab05e Mon Sep 17 00:00:00 2001 From: khbminus Date: Fri, 3 Feb 2023 23:41:22 +0100 Subject: [PATCH 07/18] Fixed multiple version constraints & added `--extra-index-url` --- .../tasks/generate/GenerateRequirements.kt | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 6243ab01..bcd84b8a 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,6 +1,6 @@ package io.paddle.plugin.python.tasks.generate -import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository +import io.paddle.plugin.python.extensions.repositories import io.paddle.plugin.python.extensions.requirements import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject @@ -17,30 +17,21 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { project.tasks.getOrFail("resolveInterpreter") ) + project.subprojects.getAllTasksById(this.id) + override fun act() { + // TODO: add support of find-links val notResolved = project.requirements.descriptors val resolved = project.requirements.resolved - val parsedDependencies = buildList { - notResolved.forEach { descriptor -> - val resolvedPackage = resolved.find { it.name == descriptor.name } - val resolvePath = resolvedPackage?.repo?.let { - if (it != PyPackageRepository.PYPI_REPOSITORY) " @ ${resolvedPackage.distributionUrl} " else "" - } ?: "" // unresolved package? - descriptor.versionSpecifier?.clauses?.forEach { version -> - add("${descriptor.name}$resolvePath $version") - } ?: add("${descriptor.name}$resolvePath") - } - } - processDependencies(parsedDependencies) - } + val requirementsFile = File(REQUIREMENTS_FILE).also { it.writeText("") } - private fun processDependencies(dependencies: List) { - val requirementsFile = File(project.workDir, REQUIREMENTS_FILE) - .also { it.writeText("") } // Clear file contents - requirementsFile.writeText("") - dependencies.forEach { - requirementsFile.appendText(it) - requirementsFile.appendText("\n") + // FIXME: local/packages with direct link are not printed correctly + notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> + if (repo != null && repo != project.repositories.resolved.primarySource) { + requirementsFile.appendText("--extra-index-url ${repo.url}\n") + } + pkgs.forEach { + requirementsFile.appendText("${it.name}${it.versionSpecifier?.clauses?.joinToString(separator = ", ", prefix = " ") ?: ""}\n") + } } } From e16eab31c72550a9bdd9b499f4ab09fa805b0b10 Mon Sep 17 00:00:00 2001 From: khbminus Date: Fri, 3 Feb 2023 23:45:23 +0100 Subject: [PATCH 08/18] Cleaned up build.gradle.kts --- plugins/python/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/python/build.gradle.kts b/plugins/python/build.gradle.kts index 61d5b177..b9ad86a8 100644 --- a/plugins/python/build.gradle.kts +++ b/plugins/python/build.gradle.kts @@ -32,9 +32,6 @@ dependencies { implementation("com.github.javakeyring:java-keyring:1.0.1") - implementation("com.akuleshov7:ktoml-core:0.3.0") - implementation("com.akuleshov7:ktoml-file:0.3.0") - testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") testImplementation("io.kotest:kotest-runner-junit5:5.4.1") testImplementation("io.kotest:kotest-assertions-core:5.4.1") From 412fae0e2933738b02e42de55a5e9f4a8a5f390d Mon Sep 17 00:00:00 2001 From: khbminus Date: Sun, 12 Feb 2023 15:43:44 +0100 Subject: [PATCH 09/18] Fixed comments in PR --- .../tasks/generate/GenerateRequirements.kt | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index bcd84b8a..ecda4031 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,40 +1,55 @@ package io.paddle.plugin.python.tasks.generate -import io.paddle.plugin.python.extensions.repositories -import io.paddle.plugin.python.extensions.requirements +import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository +import io.paddle.plugin.python.extensions.* import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject import io.paddle.tasks.Task import io.paddle.tasks.incremental.IncrementalTask +import io.paddle.utils.hash.Hashable +import io.paddle.utils.hash.hashable import java.io.File class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { override val group: String = PythonPluginTaskGroups.GENERATE override val id: String = "requirements" + override val inputs: List + get() = listOf(project.requirements.descriptors.hashable(), project.requirements.resolved.map { it.toString().hashable() }.toList().hashable(), + project.repositories.descriptors.hashable()) + override val outputs: List + get() = listOf(getRequirementsText().hashable()) override val dependencies: List get() = listOf( project.tasks.getOrFail("resolveRepositories"), project.tasks.getOrFail("resolveInterpreter") ) + project.subprojects.getAllTasksById(this.id) - - override fun act() { + private fun getRequirementsText(): String { // TODO: add support of find-links val notResolved = project.requirements.descriptors val resolved = project.requirements.resolved - val requirementsFile = File(REQUIREMENTS_FILE).also { it.writeText("") } // FIXME: local/packages with direct link are not printed correctly - notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> - if (repo != null && repo != project.repositories.resolved.primarySource) { - requirementsFile.appendText("--extra-index-url ${repo.url}\n") + return buildString { + if (project.repositories.resolved.primarySource != PyPackageRepository.PYPI_REPOSITORY) { + appendLine("--index-url ${project.repositories.resolved.primarySource.url}") } - pkgs.forEach { - requirementsFile.appendText("${it.name}${it.versionSpecifier?.clauses?.joinToString(separator = ", ", prefix = " ") ?: ""}\n") + notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> + if (repo != null && repo != project.repositories.resolved.primarySource) { + appendLine("--extra-index-url ${repo.url}") + } + pkgs.forEach { + appendLine("${it.name}${it.versionSpecifier?.clauses?.joinToString(separator = ", ", prefix = " ") ?: ""}") + } } } } + override fun act() { + File(project.workDir, REQUIREMENTS_FILE).writeText(getRequirementsText()) + + } + companion object { const val REQUIREMENTS_FILE = "requirements.txt" } From 8a7043de437fd4963af986903855946f7c77800f Mon Sep 17 00:00:00 2001 From: khbminus Date: Mon, 13 Feb 2023 21:42:58 +0100 Subject: [PATCH 10/18] Added resolving `--find-link` after `pip resolve`. It accidentally successfully installed. So I don't think I need some researches --- .../python/dependencies/packages/PyPackage.kt | 3 +- .../repositories/PyPackageRepositories.kt | 25 ++++-- .../dependencies/resolvers/PipResolver.kt | 80 ++++++++++--------- .../plugin/python/extensions/Repositories.kt | 7 +- .../paddle/plugin/python/utils/CommonUtils.kt | 10 ++- 5 files changed, 76 insertions(+), 49 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt index 7b4542a2..ef9d737e 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt @@ -15,7 +15,8 @@ class PyPackage( override val version: PyPackageVersion, @Serializable(with = PyPackageRepoMetadataSerializer::class) override val repo: PyPackageRepository, override val distributionUrl: PyPackageUrl, - var comesFrom: PyPackage? = null + var comesFrom: PyPackage? = null, + val findLink: String? = null ) : IResolvedPyPackage { override fun hashCode(): Int { if (distributionUrl.contains('#')) { diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt index ce74ef6b..a69244ff 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt @@ -4,9 +4,7 @@ import io.paddle.plugin.python.dependencies.authentication.authProvider import io.paddle.plugin.python.dependencies.index.distributions.PyDistributionInfo import io.paddle.plugin.python.extensions.Repositories import io.paddle.plugin.python.extensions.pyLocations -import io.paddle.plugin.python.utils.PyPackageName -import io.paddle.plugin.python.utils.isValidUrl -import io.paddle.plugin.python.utils.parallelForEach +import io.paddle.plugin.python.utils.* import io.paddle.project.PaddleProject import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -15,12 +13,13 @@ import kotlinx.coroutines.runBlocking class PyPackageRepositories( private val repositories: Set, val primarySource: PyPackageRepository, + val findLinks: List, val project: PaddleProject, useCachedIndex: Boolean = true, downloadIndex: Boolean = false ) { companion object { - fun resolve(repoDescriptors: List, project: PaddleProject): PyPackageRepositories { + fun resolve(repoDescriptors: List, project: PaddleProject, findLinks: List): PyPackageRepositories { val repositories = hashSetOf(PyPackageRepository.PYPI_REPOSITORY) var primarySource = PyPackageRepository.PYPI_REPOSITORY @@ -41,8 +40,16 @@ class PyPackageRepositories( repositories.add(repo) } - - return PyPackageRepositories(repositories, primarySource, project) + findLinks.forEach { + require(it.isValidUrl() || it.isValidPath()) { "The provided find link is invalid: $it" } + } + findLinks.map { + when { + it.isValidPath() -> "file://$it" + else -> it + } + } + return PyPackageRepositories(repositories, primarySource, findLinks, project) } private fun updateIndex(repositories: Set, project: PaddleProject) = runBlocking { @@ -53,7 +60,7 @@ class PyPackageRepositories( } catch (e: Throwable) { project.terminal.warn( "Failed to update index for PyPI repository: ${it.urlSimple}. " + - "Autocompletion for package names will not be available at the moment." + "Autocompletion for package names will not be available at the moment." ) } } @@ -131,6 +138,10 @@ class PyPackageRepositories( add(credentials.authenticate(repo.urlSimple)) } } + for (link in this@PyPackageRepositories.findLinks) { + add("--find-link") + add(link) + } } fun findByName(name: String): PyPackageRepository? { diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt index 6f77d1dd..e859c17d 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt @@ -4,20 +4,16 @@ import io.paddle.plugin.python.dependencies.index.distributions.ArchivePyDistrib import io.paddle.plugin.python.dependencies.index.distributions.WheelPyDistributionInfo import io.paddle.plugin.python.dependencies.index.webIndexer import io.paddle.plugin.python.dependencies.packages.PyPackage +import io.paddle.plugin.python.dependencies.repositories.PyPackageRepositories import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository import io.paddle.plugin.python.extensions.* -import io.paddle.plugin.python.utils.PyPackageUrl -import io.paddle.plugin.python.utils.cached -import io.paddle.plugin.python.utils.getSecure -import io.paddle.plugin.python.utils.trimmedEquals +import io.paddle.plugin.python.utils.* import io.paddle.project.PaddleProject import io.paddle.project.extensions.routeAsString import io.paddle.tasks.Task import io.paddle.utils.hash.hashable import kotlinx.coroutines.runBlocking -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.builtins.SetSerializer -import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.builtins.* import java.io.File import java.net.URI import kotlin.io.path.absolutePathString @@ -39,7 +35,7 @@ object PipResolver { ) { val requirementsAsPipArgs = project.requirements.descriptors.map { it.toString() } + - project.subprojects.flatMap { subproject -> subproject.requirements.resolved.map { it.toString() } } + project.subprojects.flatMap { subproject -> subproject.requirements.resolved.map { it.toString() } } val pipResolveArgs = listOf("-m", "pip", "resolve") + requirementsAsPipArgs + project.repositories.resolved.asPipArgs val executable = project.environment.localInterpreterPath.absolutePathString() @@ -78,8 +74,8 @@ object PipResolver { val pkg = project.environment.venv.findPackageWithNameOrNull(name) ?: throw Task.ActException( "Could not find existing package $name in ${project.environment.venv.path}: " + - "most probably, it does not contain PyPackage.json file in its .dist-info folder to be indexed. " + - "Please, consider re-installing this package using Paddle." + "most probably, it does not contain PyPackage.json file in its .dist-info folder to be indexed. " + + "Please, consider re-installing this package using Paddle." ) satisfiedRequirements.add(pkg) } @@ -114,38 +110,48 @@ object PipResolver { ?: throw Task.ActException("FIXME: Unknown distribution type: $filename") val version = pyDistributionInfo.version + val findLink = project.repositories.resolved.isResolvedByFindLink(distributionUrl) - val repo = if (repoUrl == "None") { // it was resolved as a local file distribution file://... - runBlocking { - project.webIndexer.getDistributionUrl( - pyDistributionInfo, - PyPackageRepository.PYPI_REPOSITORY - ) - } // if null, it was not found in the PyPi repo - ?: if (project.pythonRegistry.autoRemove) { - val localDistribution = File(URI(distributionUrl)) - if (!localDistribution.exists()) { - throw Task.ActException("Failed to delete local distribution $distributionUrl: file not found.") - } - if (!localDistribution.delete()) { - throw Task.ActException("Failed to delete local distribution $distributionUrl. Please, do it manually and re-run the task.") - } - retry = true - } else { - throw Task.ActException( - "Distribution $filename was not found in the repository ${PyPackageRepository.PYPI_REPOSITORY.url.getSecure()}.\n" + + + val repo = when { + findLink != null -> { + project.repositories.resolved.primarySource // FIXME: make this null requires a lot of code work + } + + repoUrl == "None" -> { // it was resolved as a local file distribution file://... + runBlocking { + project.webIndexer.getDistributionUrl( + pyDistributionInfo, + PyPackageRepository.PYPI_REPOSITORY + ) + } // if null, it was not found in the PyPi repo + ?: if (project.pythonRegistry.autoRemove) { + val localDistribution = File(URI(distributionUrl)) + if (!localDistribution.exists()) { + throw Task.ActException("Failed to delete local distribution $distributionUrl: file not found.") + } + if (!localDistribution.delete()) { + throw Task.ActException("Failed to delete local distribution $distributionUrl. Please, do it manually and re-run the task.") + } + retry = true + } else { + throw Task.ActException( + "Distribution $filename was not found in the repository ${PyPackageRepository.PYPI_REPOSITORY.url.getSecure()}.\n" + "It is possible that it was resolved from your local cache, " + "which is deprecated since it is not available online anymore.\n" + "Please, consider removing $distributionUrl from cache and re-running the task." - ) - } - PyPackageRepository.PYPI_REPOSITORY - } else { - project.repositories.resolved.all.find { it.url.trimmedEquals(repoUrl) } - ?: throw IllegalStateException("Unknown repository: $repoUrl") + ) + } + PyPackageRepository.PYPI_REPOSITORY + } + + else -> { + project.repositories.resolved.all.find { it.url.trimmedEquals(repoUrl) } + ?: throw IllegalStateException("Unknown repository: $repoUrl") + } } - val pkg = PyPackage(name, version, repo, distributionUrl) + val pkg = PyPackage(name, version, repo, distributionUrl, findLink = findLink) comesFromUrlByPackage[pkg] = comesFromDistributionUrl } @@ -162,5 +168,7 @@ object PipResolver { return comesFromUrlByPackage.keys + satisfiedRequirements } + private fun PyPackageRepositories.isResolvedByFindLink(url: String): PyUrl? = findLinks.find { url.startsWith(url) } + class RetrySignal : Exception() } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt index 9dfebe52..7bf54af5 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt @@ -15,10 +15,10 @@ import io.paddle.utils.hash.hashable val PaddleProject.repositories: Repositories get() = checkNotNull(extensions.get(Repositories.Extension.key)) { "Could not load extension Repositories for project $routeAsString" } -class Repositories(val project: PaddleProject, val descriptors: List) : Hashable { +class Repositories(val project: PaddleProject, val descriptors: List, val findLinks: List) : Hashable { val resolved: PyPackageRepositories by lazy { - PyPackageRepositories.resolve(descriptors, project) + PyPackageRepositories.resolve(descriptors, project, findLinks) } object Extension : PaddleProject.Extension { @@ -27,6 +27,7 @@ class Repositories(val project: PaddleProject, val descriptors: List @Suppress("UNCHECKED_CAST") override fun create(project: PaddleProject): Repositories { val reposConfig = project.config.get>>("repositories") ?: emptyList() + val findLinks = project.config.get>("findLinks") ?: emptyList() val descriptors = reposConfig.map { repo -> val repoName = checkNotNull(repo["name"]) { @@ -63,7 +64,7 @@ class Repositories(val project: PaddleProject, val descriptors: List ) } - return Repositories(project, descriptors) + return Repositories(project, descriptors, findLinks) } } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/utils/CommonUtils.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/utils/CommonUtils.kt index b08acf99..b31fa66c 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/utils/CommonUtils.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/utils/CommonUtils.kt @@ -4,8 +4,7 @@ import io.paddle.terminal.Terminal import kotlinx.coroutines.* import java.io.File import java.net.URL -import java.nio.file.Files -import java.nio.file.Path +import java.nio.file.* import java.util.* @@ -28,6 +27,13 @@ fun String.isValidUrl(): Boolean = try { false } +fun String.isValidPath(): Boolean = try { + Paths.get(this) + true +} catch (e: Exception) { + false +} + suspend fun Iterable.parallelForEach(action: suspend (A) -> Unit): Unit = coroutineScope { map { launch { action(it) } }.joinAll() } From 9d669b738e30f1061ccab6093bc6ad293c41a2d0 Mon Sep 17 00:00:00 2001 From: khbminus Date: Mon, 13 Feb 2023 22:24:57 +0100 Subject: [PATCH 11/18] Added `--find-links` in generation of requirements and fixed `--[extra]-index-url` --- .../plugin/python/tasks/generate/GenerateRequirements.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index ecda4031..bf7c2a4d 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -1,7 +1,8 @@ package io.paddle.plugin.python.tasks.generate import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository -import io.paddle.plugin.python.extensions.* +import io.paddle.plugin.python.extensions.repositories +import io.paddle.plugin.python.extensions.requirements import io.paddle.plugin.python.tasks.PythonPluginTaskGroups import io.paddle.project.PaddleProject import io.paddle.tasks.Task @@ -25,18 +26,18 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { ) + project.subprojects.getAllTasksById(this.id) private fun getRequirementsText(): String { - // TODO: add support of find-links val notResolved = project.requirements.descriptors val resolved = project.requirements.resolved // FIXME: local/packages with direct link are not printed correctly return buildString { if (project.repositories.resolved.primarySource != PyPackageRepository.PYPI_REPOSITORY) { - appendLine("--index-url ${project.repositories.resolved.primarySource.url}") + appendLine("--index-url ${project.repositories.resolved.primarySource.urlSimple}") } + project.repositories.resolved.findLinks.forEach { appendLine("--find-links $it") } notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> if (repo != null && repo != project.repositories.resolved.primarySource) { - appendLine("--extra-index-url ${repo.url}") + appendLine("--extra-index-url ${repo.urlSimple}") } pkgs.forEach { appendLine("${it.name}${it.versionSpecifier?.clauses?.joinToString(separator = ", ", prefix = " ") ?: ""}") From fec671f4d310a02a338f47ca490218e23f67e380 Mon Sep 17 00:00:00 2001 From: khbminus Date: Tue, 14 Feb 2023 11:36:28 +0100 Subject: [PATCH 12/18] Added `noIndex` in environment section of `paddle.yaml` to control `--no-index` in resolve --- .../plugin/python/dependencies/resolvers/PipResolver.kt | 3 ++- .../kotlin/io/paddle/plugin/python/extensions/Environment.kt | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt index e859c17d..3badadf5 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt @@ -36,8 +36,9 @@ object PipResolver { val requirementsAsPipArgs = project.requirements.descriptors.map { it.toString() } + project.subprojects.flatMap { subproject -> subproject.requirements.resolved.map { it.toString() } } + val noIndexFlag = listOf(if (project.environment.noIndex) {"--no-index"} else "") val pipResolveArgs = - listOf("-m", "pip", "resolve") + requirementsAsPipArgs + project.repositories.resolved.asPipArgs + listOf("-m", "pip", "resolve") + requirementsAsPipArgs + project.repositories.resolved.asPipArgs + noIndexFlag val executable = project.environment.localInterpreterPath.absolutePathString() val input = (pipResolveArgs + executable).map { it.hashable() }.hashable().hash() diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Environment.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Environment.kt index a858162c..99ffe714 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Environment.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Environment.kt @@ -26,7 +26,7 @@ import kotlin.io.path.absolutePathString val PaddleProject.environment: Environment get() = checkNotNull(extensions.get(Environment.Extension.key)) { "Could not load extension Environment for project $routeAsString" } -class Environment(val project: PaddleProject, val venv: VenvDir) : Hashable { +class Environment(val project: PaddleProject, val venv: VenvDir, val noIndex: Boolean) : Hashable { val localInterpreterPath: Path get() = venv.getInterpreterPath(project) @@ -47,9 +47,10 @@ class Environment(val project: PaddleProject, val venv: VenvDir) : Hashable { override fun create(project: PaddleProject): Environment { val config = object : ConfigurationView("environment", project.config) { val venv by string("path", default = ".venv") + val noIndex by lazy { get("noIndex")?.toBoolean() ?: false } } - return Environment(project, VenvDir(File(project.workDir, config.venv))) + return Environment(project, VenvDir(File(project.workDir, config.venv)), config.noIndex) } } From 3ba3fc48ce12ef815b011f5c2dcab60498d1c468 Mon Sep 17 00:00:00 2001 From: khbminus Date: Wed, 15 Feb 2023 13:47:35 +0100 Subject: [PATCH 13/18] Some bug fixes --- .../python/dependencies/repositories/PyPackageRepositories.kt | 4 ++-- .../plugin/python/dependencies/resolvers/PipResolver.kt | 2 +- .../kotlin/io/paddle/plugin/python/extensions/Repositories.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt index a69244ff..681edeaa 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt @@ -43,13 +43,13 @@ class PyPackageRepositories( findLinks.forEach { require(it.isValidUrl() || it.isValidPath()) { "The provided find link is invalid: $it" } } - findLinks.map { + val processedFindLinks = findLinks.map { when { it.isValidPath() -> "file://$it" else -> it } } - return PyPackageRepositories(repositories, primarySource, findLinks, project) + return PyPackageRepositories(repositories, primarySource, processedFindLinks, project) } private fun updateIndex(repositories: Set, project: PaddleProject) = runBlocking { diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt index 3badadf5..2f14afc4 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt @@ -36,7 +36,7 @@ object PipResolver { val requirementsAsPipArgs = project.requirements.descriptors.map { it.toString() } + project.subprojects.flatMap { subproject -> subproject.requirements.resolved.map { it.toString() } } - val noIndexFlag = listOf(if (project.environment.noIndex) {"--no-index"} else "") + val noIndexFlag = if (project.environment.noIndex) listOf("--no-index") else emptyList() val pipResolveArgs = listOf("-m", "pip", "resolve") + requirementsAsPipArgs + project.repositories.resolved.asPipArgs + noIndexFlag val executable = project.environment.localInterpreterPath.absolutePathString() diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt index 7bf54af5..1855694f 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/extensions/Repositories.kt @@ -96,7 +96,7 @@ class Repositories(val project: PaddleProject, val descriptors: List } override fun hash(): String { - return descriptors.hashable().hash() + return (descriptors + findLinks.map { it.hashable() }).hashable().hash() } } From f3a18b2bc7c56739e1b6b5d688eccd19ca2caca6 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Wed, 1 Mar 2023 16:20:53 +0100 Subject: [PATCH 14/18] Naming fixes --- .../plugin/python/dependencies/packages/PyPackage.kt | 5 ++--- .../dependencies/repositories/PyPackageRepositories.kt | 8 +++----- .../python/dependencies/resolvers/PipResolver.kt | 10 +++++----- .../python/tasks/generate/GenerateRequirements.kt | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt index ef9d737e..ebb795c3 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/packages/PyPackage.kt @@ -2,8 +2,7 @@ package io.paddle.plugin.python.dependencies.packages import io.paddle.plugin.python.dependencies.repositories.PyPackageRepoMetadataSerializer import io.paddle.plugin.python.dependencies.repositories.PyPackageRepository -import io.paddle.plugin.python.utils.PyPackageName -import io.paddle.plugin.python.utils.PyPackageUrl +import io.paddle.plugin.python.utils.* import kotlinx.serialization.Serializable /** @@ -16,7 +15,7 @@ class PyPackage( @Serializable(with = PyPackageRepoMetadataSerializer::class) override val repo: PyPackageRepository, override val distributionUrl: PyPackageUrl, var comesFrom: PyPackage? = null, - val findLink: String? = null + val findLinkSource: PyUrl? = null ) : IResolvedPyPackage { override fun hashCode(): Int { if (distributionUrl.contains('#')) { diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt index 681edeaa..6f31d3cf 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt @@ -6,14 +6,12 @@ import io.paddle.plugin.python.extensions.Repositories import io.paddle.plugin.python.extensions.pyLocations import io.paddle.plugin.python.utils.* import io.paddle.project.PaddleProject -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.* class PyPackageRepositories( private val repositories: Set, val primarySource: PyPackageRepository, - val findLinks: List, + val linkSources: List, val project: PaddleProject, useCachedIndex: Boolean = true, downloadIndex: Boolean = false @@ -138,7 +136,7 @@ class PyPackageRepositories( add(credentials.authenticate(repo.urlSimple)) } } - for (link in this@PyPackageRepositories.findLinks) { + for (link in this@PyPackageRepositories.linkSources) { add("--find-link") add(link) } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt index 2f14afc4..77a5163e 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/resolvers/PipResolver.kt @@ -111,11 +111,10 @@ object PipResolver { ?: throw Task.ActException("FIXME: Unknown distribution type: $filename") val version = pyDistributionInfo.version - val findLink = project.repositories.resolved.isResolvedByFindLink(distributionUrl) - + val findLinkSourceUrl = distributionUrl.findLinkSourceIn(project.repositories.resolved) val repo = when { - findLink != null -> { + findLinkSourceUrl != null -> { project.repositories.resolved.primarySource // FIXME: make this null requires a lot of code work } @@ -152,7 +151,7 @@ object PipResolver { } } - val pkg = PyPackage(name, version, repo, distributionUrl, findLink = findLink) + val pkg = PyPackage(name, version, repo, distributionUrl, findLinkSource = findLinkSourceUrl) comesFromUrlByPackage[pkg] = comesFromDistributionUrl } @@ -169,7 +168,8 @@ object PipResolver { return comesFromUrlByPackage.keys + satisfiedRequirements } - private fun PyPackageRepositories.isResolvedByFindLink(url: String): PyUrl? = findLinks.find { url.startsWith(url) } + private fun PyPackageUrl.findLinkSourceIn(repositories: PyPackageRepositories): PyUrl? = + repositories.linkSources.find { findLinksSource -> this.startsWith(findLinksSource) } class RetrySignal : Exception() } diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index bf7c2a4d..cb6fb5f2 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -34,7 +34,7 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { if (project.repositories.resolved.primarySource != PyPackageRepository.PYPI_REPOSITORY) { appendLine("--index-url ${project.repositories.resolved.primarySource.urlSimple}") } - project.repositories.resolved.findLinks.forEach { appendLine("--find-links $it") } + project.repositories.resolved.linkSources.forEach { appendLine("--find-links $it") } notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> if (repo != null && repo != project.repositories.resolved.primarySource) { appendLine("--extra-index-url ${repo.urlSimple}") From d5b9dc1a3bacb7778f613ebf025317f4f7ff96e4 Mon Sep 17 00:00:00 2001 From: khbminus Date: Thu, 2 Mar 2023 20:00:45 +0100 Subject: [PATCH 15/18] Minor fixes after the third review --- .../python/tasks/generate/GenerateRequirements.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index cb6fb5f2..59ff61a1 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -22,7 +22,8 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { override val dependencies: List get() = listOf( project.tasks.getOrFail("resolveRepositories"), - project.tasks.getOrFail("resolveInterpreter") + project.tasks.getOrFail("resolveInterpreter"), + project.tasks.getOrFail("resolveRequirements") ) + project.subprojects.getAllTasksById(this.id) private fun getRequirementsText(): String { @@ -47,7 +48,12 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { } override fun act() { - File(project.workDir, REQUIREMENTS_FILE).writeText(getRequirementsText()) + File(project.workDir, REQUIREMENTS_FILE).run { + if (exists() && this.readText().isNotEmpty()) { + throw ActException("The requirements.txt file in ${project.workDir.absolutePath} is exists. Please clear the file, or delete it.") + } + writeText(getRequirementsText()) + } } From 9b281bef013d618125553c5632ce42c06a9ff176 Mon Sep 17 00:00:00 2001 From: khbminus Date: Fri, 3 Mar 2023 21:51:34 +0100 Subject: [PATCH 16/18] Appended README.md and paddle-schema.json Added options for requirements task & find link --- README.md | 27 +++++++++++++++++++ .../main/resources/schema/paddle-schema.json | 11 ++++++++ 2 files changed, 38 insertions(+) diff --git a/README.md b/README.md index 93dfdf3c..d9e95ec8 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ environment, running tasks, and much more. - [Repositories](#repositories) - [Authentication](#authentication) - [Requirements](#requirements) + - [Find links](#find-links) - [Tasks section](#tasks-section) - [Run](#tasks-section) - [Test](#tasks-section) @@ -391,6 +392,8 @@ environment: your platform given [here](https://github.com/pyenv/pyenv/wiki#suggested-build-environment). - The downloaded and installed interpreter is cached in the `~/.paddle/interpreters` folder. +- `noIndex` (*optional*): if True, this ignores the PyPi index, and make resolving only with url + from `findLinks` section. The flag is set to `False` by default. #### Repositories @@ -543,6 +546,26 @@ convert it to its own format. Copy-paste example +#### Find links + +`findLink` is a list of URLs or paths to the external non-indexed packages (e.g. local-built +package). This is similar to pip's `--find-link` option. + +For local path or URLs starting from `file://` to a directory, then PyPI will look for +archives in the directory. + +For paths and URLs to an HTML file, PyPI will look for link to archives as +sdist (`.tar.gz`) or wheel (`.whl`). + +```yaml +findLinks: + - /home/example/sample-wheel/dist + - https://example.com/python_packages.html + - file:///usr/share/packages/sample-wheel.whl +``` + +**NB**: VCS links (e.g. `git://`) are not supported. + #### Tasks section The `tasks` section consists of several subsections that provide run configurations for @@ -675,6 +698,10 @@ Here is a reference for all the built-in Paddle tasks available at the moment. - `pylint`: runs [Pylint](https://pylint.pycqa.org/en/latest/) linter on the `sources` of the Paddle project. +- `requirements`: generates `requirements.txt` in the root directory of every project. + - Note, that generated `requirements.txt` does not represent actual structure of Paddle source. + It would only generate dependencies for a project. + ## Example: multi-project build Let's consider the following example of a Paddle multi-project build: the parental project in the monorepo does not diff --git a/idea/src/main/resources/schema/paddle-schema.json b/idea/src/main/resources/schema/paddle-schema.json index 3dd33b68..49021122 100644 --- a/idea/src/main/resources/schema/paddle-schema.json +++ b/idea/src/main/resources/schema/paddle-schema.json @@ -108,6 +108,10 @@ }, "python": { "description": "Version of the Python interpreter to be used" + }, + "noIndex": { + "description": "Ignore package index (only looking at --find-links URLs instead)", + "type": "boolean" } } }, @@ -153,6 +157,13 @@ } } }, + "findLinks": { + "description": "List of links, that will be appended as --find-link argument on the resolve stage", + "type": "array", + "items": { + "type": "string" + } + }, "repositories": { "description": "List of the available PyPI repositories. Any custom repository will have precedence over pypi.org", "type": "array", From a82419e74de1399dbbb39681bf91a6e13eb43105 Mon Sep 17 00:00:00 2001 From: khbminus Date: Mon, 6 Mar 2023 17:43:05 +0100 Subject: [PATCH 17/18] Added warning message & fixed bug with `url` --- .../repositories/PyPackageRepositories.kt | 4 ++-- .../python/tasks/generate/GenerateRequirements.kt | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt index 6f31d3cf..d9ba0c49 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/dependencies/repositories/PyPackageRepositories.kt @@ -43,8 +43,8 @@ class PyPackageRepositories( } val processedFindLinks = findLinks.map { when { - it.isValidPath() -> "file://$it" - else -> it + it.isValidUrl() -> it + else -> "file://$it" } } return PyPackageRepositories(repositories, primarySource, processedFindLinks, project) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 59ff61a1..3aec7a5a 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -15,8 +15,10 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { override val group: String = PythonPluginTaskGroups.GENERATE override val id: String = "requirements" override val inputs: List - get() = listOf(project.requirements.descriptors.hashable(), project.requirements.resolved.map { it.toString().hashable() }.toList().hashable(), - project.repositories.descriptors.hashable()) + get() = listOf( + project.requirements.descriptors.hashable(), project.requirements.resolved.map { it.toString().hashable() }.toList().hashable(), + project.repositories.descriptors.hashable() + ) override val outputs: List get() = listOf(getRequirementsText().hashable()) override val dependencies: List @@ -35,7 +37,7 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { if (project.repositories.resolved.primarySource != PyPackageRepository.PYPI_REPOSITORY) { appendLine("--index-url ${project.repositories.resolved.primarySource.urlSimple}") } - project.repositories.resolved.linkSources.forEach { appendLine("--find-links $it") } + project.repositories.resolved.linkSources.forEach { appendLine("--find-link $it") } notResolved.groupBy { descriptor -> resolved.find { it.name == descriptor.name }?.repo }.forEach { (repo, pkgs) -> if (repo != null && repo != project.repositories.resolved.primarySource) { appendLine("--extra-index-url ${repo.urlSimple}") @@ -48,6 +50,12 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { } override fun act() { + project.terminal.warn( + "This task generates a requirements files only for this project. " + + "It will ignore all subproject dependencies and subproject packages. " + + "If you want to install the project without paddle, " + + "you probably need to install all the requirements and correctly set PYTHONPATH environment variable." + ) File(project.workDir, REQUIREMENTS_FILE).run { if (exists() && this.readText().isNotEmpty()) { throw ActException("The requirements.txt file in ${project.workDir.absolutePath} is exists. Please clear the file, or delete it.") From 805e181cb608fadb99c63e4d25465535efe9426a Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Mon, 13 Mar 2023 13:14:24 +0100 Subject: [PATCH 18/18] Fix grammar --- .../paddle/plugin/python/tasks/generate/GenerateRequirements.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt index 3aec7a5a..5e5297fc 100644 --- a/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt +++ b/plugins/python/src/main/kotlin/io/paddle/plugin/python/tasks/generate/GenerateRequirements.kt @@ -58,7 +58,7 @@ class GenerateRequirements(project: PaddleProject) : IncrementalTask(project) { ) File(project.workDir, REQUIREMENTS_FILE).run { if (exists() && this.readText().isNotEmpty()) { - throw ActException("The requirements.txt file in ${project.workDir.absolutePath} is exists. Please clear the file, or delete it.") + throw ActException("The requirements.txt file in ${project.workDir.absolutePath} already exists.") } writeText(getRequirementsText()) }