mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-21 05:51:25 +07:00
PY-79488 Automatically exclude root-level ".venv" directories in uv projects
GitOrigin-RevId: 1aa3befee0151ed6dce480ecaa7aef1e32ed9a3c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5524cf2451
commit
4f52bfea7a
@@ -1,7 +1,6 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.projectModel
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.project.ContentRootData
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.platform.backend.workspace.workspaceModel
|
||||
@@ -15,7 +14,6 @@ import com.jetbrains.python.PyBundle
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.SystemIndependent
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.div
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
@@ -120,6 +118,9 @@ abstract class BaseProjectModelService<E : EntitySource, P : ExternalProject> {
|
||||
sourceRoots = extProject.sourceRoots.map { srcRoot ->
|
||||
SourceRootEntity(srcRoot.toVirtualFileUrl(fileUrlManager), PYTHON_SOURCE_ROOT_TYPE, source)
|
||||
}
|
||||
excludedUrls = extProject.excludedRoots.map { excludedRoot ->
|
||||
ExcludeUrlEntity(excludedRoot.toVirtualFileUrl(fileUrlManager), source)
|
||||
}
|
||||
})
|
||||
exModuleOptions = ExternalSystemModuleOptionsEntity(source) {
|
||||
externalSystem = systemName
|
||||
|
||||
@@ -21,6 +21,8 @@ data class PoetryProject(
|
||||
) : ExternalProject {
|
||||
override val sourceRoots: List<Path>
|
||||
get() = listOfNotNull((root / "src").takeIf { it.isDirectory() })
|
||||
override val excludedRoots: List<Path>
|
||||
get() = emptyList()
|
||||
|
||||
// Poetry projects don't have any declarative hierarchical structure
|
||||
override val fullName: String?
|
||||
|
||||
@@ -23,6 +23,7 @@ interface ExternalProject {
|
||||
val root: Path
|
||||
val dependencies: List<ExternalProjectDependency>
|
||||
val sourceRoots: List<Path>
|
||||
val excludedRoots: List<Path>
|
||||
|
||||
/**
|
||||
* The colon separated fully qualified name of the project in the form `root:subproject:subsubproject`
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.nio.file.FileVisitResult
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.PathMatcher
|
||||
import kotlin.io.path.*
|
||||
import kotlin.io.path.isDirectory
|
||||
|
||||
private const val DEFAULT_VENV_DIR = ".venv"
|
||||
|
||||
@@ -26,6 +25,8 @@ data class UvProject(
|
||||
) : ExternalProject {
|
||||
override val sourceRoots: List<Path>
|
||||
get() = listOfNotNull((root / "src").takeIf { it.isDirectory() })
|
||||
override val excludedRoots: List<Path>
|
||||
get() = listOfNotNull((root / DEFAULT_VENV_DIR).takeIf { it.isDirectory() })
|
||||
}
|
||||
|
||||
private data class UvPyProjectToml(
|
||||
|
||||
@@ -4,15 +4,15 @@ package com.jetbrains.python.projectModel.uv
|
||||
import com.intellij.openapi.externalSystem.testFramework.fixtures.multiProjectFixture
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.backend.workspace.workspaceModel
|
||||
import com.intellij.platform.testFramework.assertion.collectionAssertion.CollectionAssertions.assertEqualsUnordered
|
||||
import com.intellij.platform.testFramework.assertion.moduleAssertion.ContentRootAssertions
|
||||
import com.intellij.platform.testFramework.assertion.moduleAssertion.DependencyAssertions
|
||||
import com.intellij.platform.testFramework.assertion.moduleAssertion.ModuleAssertions
|
||||
import com.intellij.platform.testFramework.assertion.moduleAssertion.SourceRootAssertions
|
||||
import com.intellij.platform.workspace.jps.entities.ModuleEntity
|
||||
import com.intellij.platform.workspace.jps.entities.ModuleId
|
||||
import com.intellij.platform.workspace.jps.entities.SourceRootEntity
|
||||
import com.intellij.platform.workspace.jps.entities.SourceRootTypeId
|
||||
import com.intellij.platform.workspace.jps.entities.exModuleOptions
|
||||
import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl
|
||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.junit5.RegistryKey
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
@@ -22,6 +22,7 @@ import com.intellij.testFramework.utils.io.createFile
|
||||
import com.jetbrains.python.projectModel.BaseProjectModelService.Companion.PYTHON_SOURCE_ROOT_TYPE
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
@RegistryKey("python.project.model.uv", "true")
|
||||
@@ -54,6 +55,35 @@ class UvProjectSyncIntegrationTest {
|
||||
SourceRootAssertions.assertSourceRoots(project, "main", { it.rootTypeId == PYTHON_SOURCE_ROOT_TYPE }, testRoot.resolve("src"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `root dot venv directory is automatically excluded`() = timeoutRunBlocking {
|
||||
testRoot.createFile("pyproject.toml").writeText("""
|
||||
[project]
|
||||
name = "main"
|
||||
dependencies = []
|
||||
|
||||
[tool.uv.workspace]
|
||||
members = [
|
||||
"lib",
|
||||
]
|
||||
""".trimIndent())
|
||||
testRoot.createFile(".venv/pyvenv.cfg")
|
||||
|
||||
testRoot.createFile("lib/pyproject.toml").writeText("""
|
||||
[project]
|
||||
name = "lib"
|
||||
dependencies = []
|
||||
""".trimIndent())
|
||||
testRoot.createFile("lib/.venv/pyvenv.cfg")
|
||||
|
||||
multiprojectFixture.linkProject(project, testRoot, UvConstants.SYSTEM_ID)
|
||||
syncAllProjects(project)
|
||||
|
||||
ModuleAssertions.assertModules(project, "main", "lib")
|
||||
assertExcludedRoots(project, "main", listOf(testRoot.resolve(".venv")))
|
||||
assertExcludedRoots(project, "lib", listOf(testRoot.resolve("lib/.venv")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `projects inside dot venv are skipped`() = timeoutRunBlocking {
|
||||
testRoot.createFile("pyproject.toml").writeText("""
|
||||
@@ -170,6 +200,17 @@ class UvProjectSyncIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertExcludedRoots(project: Project, moduleName: String, expectedRoots: List<Path>) {
|
||||
val virtualFileUrlManager = project.workspaceModel.getVirtualFileUrlManager()
|
||||
val expectedUrls = expectedRoots.map { it.normalize().toVirtualFileUrl(virtualFileUrlManager) }
|
||||
ModuleAssertions.assertModuleEntity(project, moduleName) { moduleEntity ->
|
||||
val actualRoots = moduleEntity.contentRoots
|
||||
.flatMap { it.excludedUrls }
|
||||
.map { it.url }
|
||||
assertEqualsUnordered(expectedUrls, actualRoots)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.findModule(name: String): ModuleEntity? {
|
||||
return workspaceModel.currentSnapshot.resolve(ModuleId(name))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user