): Sdk? {
val homeDir = homeDirectory ?: return null
@@ -384,9 +355,6 @@ val Sdk.isReadOnly: Boolean
val Sdk.readOnlyErrorMessage: String
get() = PythonSdkReadOnlyProvider.getReadOnlyMessage(this) ?: PyBundle.message("python.sdk.read.only", name)
-private val Sdk.associatedPathFromAdditionalData: String?
- get() = (sdkAdditionalData as? PythonSdkAdditionalData)?.associatedModulePath
-
val Sdk.sdkFlavor: PythonSdkFlavor<*> get() = getOrCreateAdditionalData().flavor
private fun Sdk.isLocatedInsideModule(module: Module): Boolean {
diff --git a/python/src/com/jetbrains/python/sdk/add/v2/conda/CondaViewModel.kt b/python/src/com/jetbrains/python/sdk/add/v2/conda/CondaViewModel.kt
index 7a6171bc6ac3..3d241828ef76 100644
--- a/python/src/com/jetbrains/python/sdk/add/v2/conda/CondaViewModel.kt
+++ b/python/src/com/jetbrains/python/sdk/add/v2/conda/CondaViewModel.kt
@@ -15,8 +15,8 @@ import com.jetbrains.python.PyBundle.message
import com.jetbrains.python.conda.loadLocalPythonCondaPath
import com.jetbrains.python.errorProcessing.PyResult
import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows
-import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils
-import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
+import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlSdkUtils
+import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
import com.jetbrains.python.sdk.add.v2.FileSystem
import com.jetbrains.python.sdk.add.v2.PathHolder
import com.jetbrains.python.sdk.add.v2.PythonToolViewModel
diff --git a/python/src/com/jetbrains/python/sdk/add/v2/models.kt b/python/src/com/jetbrains/python/sdk/add/v2/models.kt
index c76f5b3a36fd..977d266d30eb 100644
--- a/python/src/com/jetbrains/python/sdk/add/v2/models.kt
+++ b/python/src/com/jetbrains/python/sdk/add/v2/models.kt
@@ -310,7 +310,7 @@ internal val PythonAddInterpreterModel
.existingSdks: List>()?.map { it.sdkWrapper.sdk } ?: emptyList()
internal suspend fun PythonAddInterpreterModel<*>.getBasePath(module: Module?): Path = withContext(Dispatchers.IO) {
- val pyProjectTomlBased = module?.let { PyProjectToml.findFile(it)?.toNioPathOrNull()?.parent }
+ val pyProjectTomlBased = module?.let { PyProjectToml.findPyProjectTomlFile(it)?.virtualFile?.toNioPathOrNull()?.parent }
pyProjectTomlBased ?: module?.baseDir?.path?.let { Path.of(it) } ?: projectPathFlows.projectPathWithDefault.first()
}
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt
deleted file mode 100644
index ac18112fe04b..000000000000
--- a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvFileHelper.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-package com.jetbrains.python.sdk.pipenv
-
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.projectRoots.Sdk
-import com.intellij.openapi.vfs.StandardFileSystems
-import com.intellij.openapi.vfs.VirtualFile
-import com.jetbrains.python.sdk.associatedModulePath
-import com.jetbrains.python.sdk.findAmongRoots
-import org.jetbrains.annotations.ApiStatus.Internal
-
-@Internal
-object PipEnvFileHelper {
- const val PIP_FILE: String = "Pipfile"
- const val PIP_FILE_LOCK: String = "Pipfile.lock"
-
- fun getPipFileLock(sdk: Sdk): VirtualFile? =
- sdk.associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) }
-
- suspend fun pipFile(module: Module): VirtualFile? = findAmongRoots(module, PIP_FILE)
-}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt
index 1bf77f3da4fd..529766af319a 100644
--- a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt
+++ b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt
@@ -5,7 +5,6 @@ import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationListener
import com.intellij.notification.NotificationType
import com.intellij.openapi.application.EDT
-import com.intellij.openapi.application.edtWriteAction
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
@@ -78,7 +77,7 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
private suspend fun notifyPipFileChanged(module: Module) {
if (module.getUserData(notificationActive) == true) return
val title = when {
- getPipFileLock(module) == null -> PyBundle.message("python.sdk.pipenv.pip.file.lock.not.found")
+ findAmongRoots(module, PIP_FILE_LOCK) == null -> PyBundle.message("python.sdk.pipenv.pip.file.lock.not.found")
else -> PyBundle.message("python.sdk.pipenv.pip.file.lock.out.of.date")
}
val content = PyBundle.message("python.sdk.pipenv.pip.file.notification.content")
@@ -129,18 +128,15 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
private suspend fun isPipFileEditor(editor: Editor): Boolean {
val file = editor.document.virtualFile ?: return false
- if (file.name != PipEnvFileHelper.PIP_FILE) return false
+ if (file.name != PIP_FILE) return false
val project = editor.project ?: return false
val module = file.getModule(project) ?: return false
- if (PipEnvFileHelper.pipFile(module) != file) return false
+ if (findAmongRoots(module, PIP_FILE) != file) return false
return module.pythonSdk?.isPipEnv == true
}
private val Document.virtualFile: VirtualFile?
get() = FileDocumentManager.getInstance().getFile(this)
- private fun VirtualFile.getModule(project: Project): Module? =
- ModuleUtil.findModuleForFile(this, project)
-
- private suspend fun getPipFileLock(module: Module): VirtualFile? = findAmongRoots(module, PipEnvFileHelper.PIP_FILE_LOCK)
+ private fun VirtualFile.getModule(project: Project): Module? = ModuleUtil.findModuleForFile(this, project)
}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipFileLockFile.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipFileLockFile.kt
new file mode 100644
index 000000000000..95b396136d34
--- /dev/null
+++ b/python/src/com/jetbrains/python/sdk/pipenv/PipFileLockFile.kt
@@ -0,0 +1,28 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.jetbrains.python.sdk.pipenv
+
+import com.intellij.openapi.projectRoots.Sdk
+import com.intellij.openapi.vfs.StandardFileSystems
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.python.requirements.icons.PythonRequirementsIcons
+import com.jetbrains.python.requirements.PyDependenciesFile
+import com.jetbrains.python.sdk.associatedModulePath
+import org.jetbrains.annotations.ApiStatus.Internal
+import javax.swing.Icon
+
+@Internal
+const val PIP_FILE: String = "Pipfile"
+
+@Internal
+const val PIP_FILE_LOCK: String = "Pipfile.lock"
+
+@Internal
+class PipFileLockFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
+ override val icon: Icon get() = PythonRequirementsIcons.Requirements
+}
+
+
+internal fun Sdk.findPipFileLockFile(): PipFileLockFile? {
+ val virtualFile = associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) }
+ return virtualFile?.let { PipFileLockFile(it) }
+}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
index dffdf9215168..eeb5d8cd00c0 100644
--- a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
+++ b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt
@@ -76,7 +76,7 @@ suspend fun setupPipEnv(
basePythonBinaryPath: PythonBinary?,
installPackages: Boolean,
): PyResult<@SystemDependent String> {
- val pipfile = projectPath.resolve(PipEnvFileHelper.PIP_FILE)
+ val pipfile = projectPath.resolve(PIP_FILE)
if (!pipfile.exists()) {
// Currently, if a Pipenv file exists inside the user's home directory, then it will NOT create a new Pipenv in the current project
diff --git a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt
index 4eb50777948a..818de1401f42 100644
--- a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt
+++ b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt
@@ -4,7 +4,7 @@ package com.jetbrains.python.sdk.poetry
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
-import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.python.pyproject.PyProjectTomlFile
import com.jetbrains.python.PyBundle
import com.jetbrains.python.errorProcessing.PyResult
import com.jetbrains.python.getOrNull
@@ -219,7 +219,7 @@ class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pr
return PackageCollectionPackageStructureNode(declared, undeclared + standalonePackages)
}
- override fun getDependencyFile(): VirtualFile? {
+ override fun getDependencyFile(): PyProjectTomlFile? {
val projectPathStr = sdk.associatedModulePath ?: return null
val projectPath = Path.of(projectPathStr)
return resolvePyProjectToml(projectPath)
diff --git a/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt b/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt
index 48986e5c49e2..27a02e18e139 100644
--- a/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt
+++ b/python/src/com/jetbrains/python/sdk/uv/UvPackageManager.kt
@@ -8,9 +8,9 @@ import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootManager
-import com.intellij.openapi.vfs.VirtualFile
import com.intellij.python.community.impl.uv.common.UV_TOOL_ID
import com.intellij.python.pyproject.PyProjectToml
+import com.intellij.python.pyproject.PyProjectTomlFile
import com.intellij.python.pyproject.model.internal.workspaceBridge.getToolWorkspaceLayout
import com.intellij.util.cancelOnDispose
import com.jetbrains.python.PyBundle.message
@@ -270,17 +270,17 @@ class UvPackageManager internal constructor(project: Project, sdk: Sdk, uvExecut
override fun updateLockedAction(): suspend () -> PyResult = suspend { syncLocked().mapSuccess { } }
private suspend fun resolvePackageName(module: Module): String {
- val pyProjectFile = PyProjectToml.findFile(module) ?: return module.name
- return PyProjectToml.parseCached(module.project, pyProjectFile)?.project?.name ?: module.name
+ val pyProjectFile = PyProjectToml.findPyProjectTomlFile(module) ?: return module.name
+ return PyProjectToml.parseCached(module.project, pyProjectFile.virtualFile)?.project?.name ?: module.name
}
// TODO PY-87712 Double check for remotes
- override fun getDependencyFile(): VirtualFile? {
+ override fun getDependencyFile(): PyProjectTomlFile? {
val uvWorkingDirectory = runBlockingMaybeCancellable { uvExecutionContextDeferred.await().workingDir }
return resolvePyProjectToml(uvWorkingDirectory)
}
- override suspend fun getDependencyFiles(): List {
+ override suspend fun getDependencyFiles(): List {
val rootFile = getDependencyFile() ?: return emptyList()
val uvWorkingDirectory = uvExecutionContextDeferred.await().workingDir
val memberModules = readAction {
@@ -289,7 +289,7 @@ class UvPackageManager internal constructor(project: Project, sdk: Sdk, uvExecut
} ?: return@readAction emptyList()
rootModule.getToolWorkspaceLayout(UV_TOOL_ID)?.memberModules.orEmpty()
}
- val memberFiles = memberModules.mapNotNull { PyProjectToml.findFile(it) }
+ val memberFiles = memberModules.mapNotNull { PyProjectToml.findPyProjectTomlFile(it) }
return listOf(rootFile) + memberFiles
}
diff --git a/python/testSrc/com/jetbrains/python/packaging/management/TestPackageManager.kt b/python/testSrc/com/jetbrains/python/packaging/management/TestPackageManager.kt
index 5e363f6bb651..34820539f930 100644
--- a/python/testSrc/com/jetbrains/python/packaging/management/TestPackageManager.kt
+++ b/python/testSrc/com/jetbrains/python/packaging/management/TestPackageManager.kt
@@ -16,9 +16,13 @@ import com.jetbrains.python.packaging.common.PythonPackageDetails
import com.jetbrains.python.packaging.common.PythonRepositoryPackageSpecification
import com.jetbrains.python.packaging.common.toPythonPackage
import com.jetbrains.python.packaging.common.toPythonPackages
-import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
+import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlFile
+import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
import com.jetbrains.python.packaging.setupPy.SetupPyHelpers
import com.jetbrains.python.psi.PyFile
+import com.jetbrains.python.requirements.PyDependenciesFile
+import com.jetbrains.python.requirements.RequirementsTxtFile
+import com.jetbrains.python.requirements.SetupPyFile
import com.jetbrains.python.sdk.associatedModuleDir
import org.jetbrains.annotations.TestOnly
@@ -80,14 +84,14 @@ class TestPythonPackageManager(project: Project, sdk: Sdk) : PythonPackageManage
return PyResult.success(listInstalledPackagesSnapshot())
}
- override fun getDependencyFile(): VirtualFile? {
+ override fun getDependencyFile(): PyDependenciesFile? {
val providerType = sdk.getUserData(REQUIREMENTS_PROVIDER_KEY) ?: return null
val moduleDir = sdk.associatedModuleDir ?: return null
return when (providerType) {
- RequirementsProviderType.REQUIREMENTS_TXT -> moduleDir.findChild("requirements.txt")
- RequirementsProviderType.SETUP_PY -> moduleDir.findChild("setup.py")
- RequirementsProviderType.ENVIRONMENT_YML -> moduleDir.findChild("environment.yml")
+ RequirementsProviderType.REQUIREMENTS_TXT -> moduleDir.findChild("requirements.txt")?.let { RequirementsTxtFile(it) }
+ RequirementsProviderType.SETUP_PY -> moduleDir.findChild("setup.py")?.let { SetupPyFile(it) }
+ RequirementsProviderType.ENVIRONMENT_YML -> moduleDir.findChild("environment.yml")?.let { CondaEnvironmentYmlFile(it) }
}
}