mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-79488 Support PEP 621-style path dependencies in Poetry
GitOrigin-RevId: fd4dfce4af8ca5cad3f2fba25aaf573d4df74d1f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a2e30a6755
commit
14d3f67525
@@ -7,9 +7,13 @@ import com.jetbrains.python.projectModel.ExternalProjectGraph
|
||||
import com.jetbrains.python.projectModel.PythonProjectModelResolver
|
||||
import org.apache.tuweni.toml.Toml
|
||||
import org.apache.tuweni.toml.TomlTable
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.*
|
||||
|
||||
// e.g. "lib @ file:///home/user/projects/main/lib"
|
||||
private val PEP_621_PATH_DEPENDENCY = """([\w-]+) @ (file:.*)""".toRegex()
|
||||
|
||||
data class PoetryProject(
|
||||
override val name: String,
|
||||
override val root: Path,
|
||||
@@ -52,15 +56,28 @@ object PoetryProjectModelResolver : PythonProjectModelResolver<PoetryProject> {
|
||||
}
|
||||
|
||||
private fun readPoetryPyProjectToml(pyprojectTomlPath: Path): PoetryPyProjectToml? {
|
||||
// TODO read editable dependencies in newer pyproject.toml
|
||||
val pyprojectToml = Toml.parse(pyprojectTomlPath)
|
||||
val projectName = pyprojectToml.getString("tool.poetry.name") ?: pyprojectToml.getString("project.name")
|
||||
if (projectName == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val moduleDependencies = pyprojectToml.getArrayOrEmpty("project.dependencies")
|
||||
.toList()
|
||||
.filterIsInstance<String>()
|
||||
.mapNotNull { depSpec ->
|
||||
val match = PEP_621_PATH_DEPENDENCY.matchEntire(depSpec)
|
||||
if (match == null) return@mapNotNull null
|
||||
val (depName, depUri) = match.destructured
|
||||
val depPath = runCatching { Path.of(URI(depUri)) }.getOrNull() ?: return@mapNotNull null
|
||||
if (depPath.isDirectory() && depPath.resolve(PoetryConstants.PYPROJECT_TOML).exists()) {
|
||||
return@mapNotNull depName to depPath
|
||||
}
|
||||
return@mapNotNull null
|
||||
}
|
||||
.toMap()
|
||||
|
||||
// Editable path dependencies can appear only inside tool.poetry.dependencies
|
||||
val moduleDependencies: Map<String, Path> = pyprojectToml.getTableOrEmpty("tool.poetry.dependencies")
|
||||
val oldStyleModuleDependencies: Map<String, Path> = pyprojectToml.getTableOrEmpty("tool.poetry.dependencies")
|
||||
.toMap().entries
|
||||
.mapNotNull { (depName, depSpec) ->
|
||||
if (depSpec is TomlTable && depSpec.getBoolean("develop") == true) {
|
||||
@@ -76,7 +93,7 @@ object PoetryProjectModelResolver : PythonProjectModelResolver<PoetryProject> {
|
||||
return PoetryPyProjectToml(
|
||||
projectName = projectName,
|
||||
root = pyprojectTomlPath.parent,
|
||||
editablePathDependencies = moduleDependencies
|
||||
editablePathDependencies = moduleDependencies.ifEmpty { oldStyleModuleDependencies }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+39
-1
@@ -54,7 +54,45 @@ class PoetryProjectSyncIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `project with path dependencies is properly mapped to IJ modules`() = timeoutRunBlocking {
|
||||
fun `project with new-style PEP-621 path dependencies`() = timeoutRunBlocking {
|
||||
testRoot.createFile("pyproject.toml").writeText("""
|
||||
[project]
|
||||
name = "main"
|
||||
dependencies = [
|
||||
"lib @ ${testRoot.toUri()}/lib"
|
||||
]
|
||||
""".trimIndent())
|
||||
|
||||
testRoot.createFile("lib/pyproject.toml").writeText("""
|
||||
[project]
|
||||
name = "lib"
|
||||
dependencies = [
|
||||
]
|
||||
""".trimIndent())
|
||||
|
||||
multiprojectFixture.linkProject(project, testRoot, PoetryConstants.SYSTEM_ID)
|
||||
syncAllProjects(project)
|
||||
|
||||
val virtualFileUrlManager = project.workspaceModel.getVirtualFileUrlManager()
|
||||
ModuleAssertions.assertModules(project, "main", "lib")
|
||||
ModuleAssertions.assertModuleEntity(project, "main") { module ->
|
||||
ContentRootAssertions.assertContentRoots(virtualFileUrlManager, module, testRoot)
|
||||
DependencyAssertions.assertDependencies(module, INHERITED_SDK, MODULE_SOURCE, "lib")
|
||||
DependencyAssertions.assertModuleDependency(module, "lib") { dependency ->
|
||||
Assertions.assertTrue(dependency.exported)
|
||||
}
|
||||
}
|
||||
|
||||
ModuleAssertions.assertModuleEntity(project, "lib") { module ->
|
||||
ContentRootAssertions.assertContentRoots(virtualFileUrlManager, module, testRoot.resolve("lib"))
|
||||
DependencyAssertions.assertDependencies(module, INHERITED_SDK, MODULE_SOURCE)
|
||||
}
|
||||
}
|
||||
|
||||
// This format of path dependencies was used before Poetry 2.0
|
||||
// https://python-poetry.org/history/#added-2
|
||||
@Test
|
||||
fun `project with old-style path dependencies`() = timeoutRunBlocking {
|
||||
testRoot.createFile("pyproject.toml").writeText("""
|
||||
[tool.poetry]
|
||||
name = "main"
|
||||
|
||||
Reference in New Issue
Block a user