diff --git a/python/src/com/jetbrains/python/packaging/PyPipEnvPackageManager.kt b/python/src/com/jetbrains/python/packaging/PyPipEnvPackageManager.kt index 907387555b67..d12b9f52f0e0 100644 --- a/python/src/com/jetbrains/python/packaging/PyPipEnvPackageManager.kt +++ b/python/src/com/jetbrains/python/packaging/PyPipEnvPackageManager.kt @@ -11,7 +11,9 @@ import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.vfs.VfsUtil import com.jetbrains.python.sdk.PythonSdkType +import com.jetbrains.python.sdk.flavors.pipFileLockRequirements import com.jetbrains.python.sdk.flavors.runPipEnv +import com.jetbrains.python.sdk.pythonSdk /** * @author vlan @@ -83,7 +85,8 @@ class PyPipEnvPackageManager(val sdk: Sdk) : PyPackageManager() { return packages ?: emptyList() } - override fun getRequirements(module: Module): List? = null + override fun getRequirements(module: Module): List? = + module.pythonSdk?.pipFileLockRequirements override fun parseRequirements(text: String): List = PyPackageUtil.fix(PyRequirement.fromText(text)) diff --git a/python/src/com/jetbrains/python/sdk/flavors/pipenv.kt b/python/src/com/jetbrains/python/sdk/flavors/pipenv.kt index 377c9dbd09e8..74c47d7e3ea6 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/pipenv.kt +++ b/python/src/com/jetbrains/python/sdk/flavors/pipenv.kt @@ -30,6 +30,9 @@ import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.PathUtil import com.jetbrains.python.packaging.PyExecutionException +import com.jetbrains.python.packaging.PyPackageManager +import com.jetbrains.python.packaging.PyPackageManagers +import com.jetbrains.python.packaging.PyRequirement import com.jetbrains.python.sdk.* import icons.PythonIcons import org.jetbrains.annotations.SystemDependent @@ -187,12 +190,33 @@ fun detectAndSetupPipEnv(project: Project?, module: Module?, existingSdks: List< } /** - * URLs of package sources configured in the Pipfile.lock of the module associated with this SDK. + * The URLs of package sources configured in the Pipfile.lock of the module associated with this SDK. */ val Sdk.pipFileLockSources: List get() = parsePipFileLock()?.meta?.sources?.mapNotNull { it.url } ?: listOf(PIPENV_DEFAULT_SOURCE_URL) +/** + * The list of requirements defined in the Pipfile.lock of the module associated with this SDK. + */ +val Sdk.pipFileLockRequirements: List? + get() { + fun toRequirements(packages: Map): List = + packages + .asSequence() + .filterNot { (_, pkg) -> pkg.editable ?: false } + .flatMap { (name, pkg) -> packageManager.parseRequirements("$name${pkg.version ?: ""}").asSequence() } + .toList() + + val pipFileLock = parsePipFileLock() ?: return null + val packages = pipFileLock.packages?.let { toRequirements(it) } ?: emptyList() + val devPackages = pipFileLock.devPackages?.let { toRequirements(it) } ?: emptyList() + return packages + devPackages + } + +private val Sdk.packageManager: PyPackageManager + get() = PyPackageManagers.getInstance().forSdk(this) + /** * A quick-fix for setting up the pipenv for the module of the current PSI element. */ @@ -249,9 +273,14 @@ private val Sdk.pipFileLock: VirtualFile? get() = associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) } -private data class PipFileLock(@SerializedName("_meta") var meta: PipFileLockMeta?) +private data class PipFileLock(@SerializedName("_meta") var meta: PipFileLockMeta?, + @SerializedName("default") var packages: Map?, + @SerializedName("develop") var devPackages: Map?) private data class PipFileLockMeta(@SerializedName("sources") var sources: List?) private data class PipFileLockSource(@SerializedName("url") var url: String?) +private data class PipFileLockPackage(@SerializedName("version") var version: String?, + @SerializedName("editable") var editable: Boolean?) +