mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-52688 support pipenv for remote targets
GitOrigin-RevId: 422467f4730b890eaf112f4ed3d82b6cd0f0907d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c4bf56ea0f
commit
f7bb047bb8
@@ -15,24 +15,20 @@ import com.jetbrains.python.packaging.management.PythonPackageInstallRequest
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.management.PythonRepositoryManager
|
||||
import com.jetbrains.python.packaging.pip.PipRepositoryManager
|
||||
import com.jetbrains.python.sdk.associatedModulePath
|
||||
import com.jetbrains.python.sdk.pipenv.PIP_FILE
|
||||
import com.jetbrains.python.sdk.pipenv.runPipEnv
|
||||
import com.jetbrains.python.sdk.pipenv.runPipEnvWithSdk
|
||||
import java.nio.file.Path
|
||||
import com.jetbrains.python.sdk.pipenv.PipEnvParser as SdkPipEnvParser
|
||||
|
||||
internal class PipEnvPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(project, sdk) {
|
||||
private val modulePath: Path?
|
||||
get() = sdk.associatedModulePath?.let { Path.of(it) }
|
||||
|
||||
override val repositoryManager: PythonRepositoryManager = PipRepositoryManager.getInstance(project)
|
||||
|
||||
override suspend fun syncLockedCommand(): PyResult<Unit> {
|
||||
return runPipEnv(modulePath, "install", "--dev").mapSuccess { }
|
||||
return runPipEnvWithSdk(sdk, "install", "--dev").mapSuccess { }
|
||||
}
|
||||
|
||||
suspend fun lock(): PyResult<Unit> {
|
||||
return runPipEnv(modulePath, "lock").mapSuccess { }
|
||||
return runPipEnvWithSdk(sdk, "lock").mapSuccess { }
|
||||
}
|
||||
|
||||
override suspend fun installPackageCommand(installRequest: PythonPackageInstallRequest, options: List<String>, module: Module?, dependencyGroup: PyDependencyGroup?): PyResult<Unit> {
|
||||
@@ -41,24 +37,24 @@ internal class PipEnvPackageManager(project: Project, sdk: Sdk) : PythonPackageM
|
||||
is PythonPackageInstallRequest.ByRepositoryPythonPackageSpecifications -> {
|
||||
|
||||
val args = listOf("install") + installRequest.specifications.map { it.nameWithVersionSpec } + options
|
||||
runPipEnv(modulePath, *args.toTypedArray()).mapSuccess { }
|
||||
runPipEnvWithSdk(sdk, *args.toTypedArray()).mapSuccess { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updatePackageCommand(vararg specifications: PythonRepositoryPackageSpecification): PyResult<Unit> {
|
||||
val args = listOf("install") + specifications.map { it.nameWithVersionSpec }
|
||||
return runPipEnv(modulePath, *args.toTypedArray()).mapSuccess { }
|
||||
return runPipEnvWithSdk(sdk, *args.toTypedArray()).mapSuccess { }
|
||||
}
|
||||
|
||||
override suspend fun uninstallPackageCommand(vararg pythonPackages: String, workspaceMember: PyWorkspaceMember?, dependencyGroup: PyDependencyGroup?): PyResult<Unit> {
|
||||
val args = listOf("uninstall") + pythonPackages.toList()
|
||||
return runPipEnv(modulePath, *args.toTypedArray()).mapSuccess { }
|
||||
return runPipEnvWithSdk(sdk, *args.toTypedArray()).mapSuccess { }
|
||||
|
||||
}
|
||||
|
||||
override suspend fun loadPackagesCommand(): PyResult<List<PythonPackage>> {
|
||||
val output = runPipEnv(modulePath, "graph", "--json")
|
||||
val output = runPipEnvWithSdk(sdk, "graph", "--json")
|
||||
output.getOr {
|
||||
return it
|
||||
}
|
||||
@@ -72,7 +68,7 @@ internal class PipEnvPackageManager(project: Project, sdk: Sdk) : PythonPackageM
|
||||
}
|
||||
|
||||
override suspend fun loadOutdatedPackagesCommand(): PyResult<List<PythonOutdatedPackage>> {
|
||||
val output = runPipEnv(modulePath, "update", "--dry-run").getOr { return it }
|
||||
val output = runPipEnvWithSdk(sdk, "update", "--dry-run").getOr { return it }
|
||||
val outdated = PipEnvParser.parseOutdatedPackagesOutput(output)
|
||||
|
||||
return PyResult.success(outdated)
|
||||
@@ -87,4 +83,4 @@ internal class PipEnvPackageManager(project: Project, sdk: Sdk) : PythonPackageM
|
||||
override val dependenciesFilesRelativePaths: List<Path>
|
||||
get() =
|
||||
listOf(Path.of(PIP_FILE))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ enum class PythonSupportedEnvironmentManagers(
|
||||
VIRTUALENV(VENV_TOOL_ID, "sdk.create.custom.virtualenv", PythonVenvIcons.VirtualEnv, sshAutoUploadRequired = false, { true }),
|
||||
CONDA(CONDA_TOOL_ID, "sdk.create.custom.conda", PythonCommunityImplCondaIcons.Anaconda, sshAutoUploadRequired = false, { true }),
|
||||
POETRY(POETRY_TOOL_ID, "sdk.create.custom.poetry", PythonCommunityImplPoetryCommonIcons.Poetry, sshAutoUploadRequired = true, { true }),
|
||||
PIPENV(PIPENV_TOOL_ID, "sdk.create.custom.pipenv", PythonCommunityImplPipenvIcons.PythonClosed, sshAutoUploadRequired = false),
|
||||
PIPENV(PIPENV_TOOL_ID, "sdk.create.custom.pipenv", PythonCommunityImplPipenvIcons.PythonClosed, sshAutoUploadRequired = true, { true }),
|
||||
UV(UV_TOOL_ID, "sdk.create.custom.uv", PythonUvCommonIcons.UV, sshAutoUploadRequired = true, { true }),
|
||||
HATCH(HATCH_TOOL_ID, "sdk.create.custom.hatch", PythonHatchIcons.Logo, sshAutoUploadRequired = true, { true }),
|
||||
PYTHON(VENV_TOOL_ID, "sdk.create.custom.python", PythonParserIcons.PythonFile, sshAutoUploadRequired = false, { true })
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.intellij.python.community.impl.pipenv.PipEnvPyTool
|
||||
import com.intellij.python.community.impl.pipenv.pipenvPath
|
||||
import com.intellij.python.pytools.PyTool
|
||||
import com.intellij.platform.util.progress.withProgressText
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.errorProcessing.ErrorSink
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
@@ -34,16 +33,19 @@ internal class EnvironmentCreatorPip<P : PathHolder>(model: PythonMutableTargetA
|
||||
|
||||
override suspend fun setupEnvSdk(moduleBasePath: Path): PyResult<Sdk> {
|
||||
val basePythonBinaryPath = model.getOrInstallBasePython()
|
||||
?: return PyResult.localizedError(message("python.sdk.provided.path.is.invalid", null))
|
||||
val pipenvExecutable = model.pipenvViewModel.pipenvExecutable.get()?.pathHolder
|
||||
?: return PyResult.localizedError(message("python.sdk.provided.path.is.invalid", null))
|
||||
|
||||
return when (basePythonBinaryPath) {
|
||||
is PathHolder.Eel -> withProgressText(message("python.sdk.progress.pipenv.creating")) {
|
||||
setupPipEnvSdkWithProgressReport(
|
||||
moduleBasePath = moduleBasePath,
|
||||
basePythonBinaryPath = basePythonBinaryPath.path,
|
||||
installPackages = false
|
||||
)
|
||||
}
|
||||
else -> PyResult.localizedError(message("target.is.not.supported", basePythonBinaryPath))
|
||||
return withProgressText(message("python.sdk.progress.pipenv.creating")) {
|
||||
setupPipEnvSdkWithProgressReport(
|
||||
moduleBasePath = moduleBasePath,
|
||||
basePythonBinaryPath = basePythonBinaryPath,
|
||||
fileSystem = model.fileSystem,
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
installPackages = false,
|
||||
targetPanelExtension = model.state.targetPanelExtension.get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.jetbrains.python.errorProcessing.emit
|
||||
import com.jetbrains.python.onFailure
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import com.jetbrains.python.sdk.associatedModuleDir
|
||||
import com.jetbrains.python.sdk.associatedModulePath
|
||||
import com.jetbrains.python.sdk.findAmongRoots
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import com.jetbrains.python.sdk.skeleton.PySkeletonUtil
|
||||
@@ -33,7 +32,6 @@ import com.jetbrains.python.statistics.PipfileWatcherIdsHolder.Companion.RUN_PIP
|
||||
import com.jetbrains.python.errorProcessing.ErrorSink
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* Watches for edits in Pipfiles inside modules with a pipenv SDK set.
|
||||
@@ -114,7 +112,7 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
|
||||
PyPackageCoroutine.launch(module.project) {
|
||||
withBackgroundProgress(module.project, description) {
|
||||
val sdk = module.pythonSdk ?: return@withBackgroundProgress
|
||||
runPipEnv(sdk.associatedModulePath?.let { Path.of(it) }, *args.toTypedArray()).onFailure {
|
||||
runPipEnvWithSdk(sdk, *args.toTypedArray()).onFailure {
|
||||
ErrorSink().emit(it, module.project)
|
||||
}
|
||||
|
||||
@@ -139,4 +137,4 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
|
||||
get() = FileDocumentManager.getInstance().getFile(this)
|
||||
|
||||
private fun VirtualFile.getModule(project: Project): Module? = ModuleUtil.findModuleForFile(this, project)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// 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.sdk.pipenv
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.execService.DownloadConfig
|
||||
import com.intellij.python.community.execService.ProcessOutputTransformer
|
||||
import com.intellij.python.community.impl.pipenv.pipenvPath
|
||||
import com.jetbrains.python.PyBundle
|
||||
@@ -13,33 +15,52 @@ import com.jetbrains.python.sdk.ToolCommandExecutor
|
||||
import com.jetbrains.python.sdk.add.v2.EelFileSystem
|
||||
import com.jetbrains.python.sdk.add.v2.FileSystem
|
||||
import com.jetbrains.python.sdk.add.v2.PathHolder
|
||||
import com.jetbrains.python.sdk.add.v2.TargetFileSystemCache
|
||||
import com.jetbrains.python.sdk.add.v2.toEelFileSystem
|
||||
import com.jetbrains.python.sdk.createSdk
|
||||
import com.jetbrains.python.sdk.impl.PySdkBundle
|
||||
import com.jetbrains.python.sdk.pySdkAdditionalData
|
||||
import com.jetbrains.python.sdk.runTool
|
||||
import com.jetbrains.python.venvReader.VirtualEnvReader
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import com.jetbrains.python.target.PyTargetAwareAdditionalData
|
||||
import com.jetbrains.python.target.PythonLanguageRuntimeConfiguration
|
||||
import com.jetbrains.python.target.ui.TargetPanelExtension
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import org.jetbrains.annotations.SystemDependent
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.createFile
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
internal val PIPENV_TOOL: ToolCommandExecutor = ToolCommandExecutor("pipenv") {
|
||||
pipenvPath
|
||||
}
|
||||
|
||||
private val PIPENV_PROJECT_DOWNLOAD_CONFIG = DownloadConfig(relativePaths = listOf(PIP_FILE, PIP_FILE_LOCK))
|
||||
private val PIPENV_PROJECT_MUTATING_COMMANDS = setOf("--python", "install", "lock", "sync", "uninstall", "update")
|
||||
|
||||
internal suspend fun <P : PathHolder> runPipEnv(
|
||||
fileSystem: FileSystem<P>,
|
||||
dirPath: Path?,
|
||||
vararg args: String,
|
||||
pipenvExecutable: P? = null,
|
||||
baseEnv: Map<String, String> = emptyMap(),
|
||||
downloadConfig: DownloadConfig? = null,
|
||||
): PyResult<String> =
|
||||
PIPENV_TOOL.runTool(
|
||||
fileSystem = fileSystem,
|
||||
pathFromSdk = pipenvExecutable?.toString(),
|
||||
dirPath = dirPath,
|
||||
args = args,
|
||||
env = baseEnv,
|
||||
downloadConfig = downloadConfig,
|
||||
)
|
||||
|
||||
@Internal
|
||||
suspend fun runPipEnv(dirPath: Path?, vararg args: String): PyResult<String> =
|
||||
PIPENV_TOOL.runTool(
|
||||
runPipEnv(
|
||||
fileSystem = dirPath.toEelFileSystem(),
|
||||
pathFromSdk = null,
|
||||
dirPath = dirPath,
|
||||
args = args,
|
||||
)
|
||||
|
||||
@Internal
|
||||
internal suspend fun <T> runPipEnv(dirPath: Path?, vararg args: String, transformer: ProcessOutputTransformer<T>): PyResult<T> =
|
||||
PIPENV_TOOL.runTool(
|
||||
fileSystem = dirPath.toEelFileSystem(),
|
||||
@@ -52,39 +73,88 @@ internal suspend fun <T> runPipEnv(dirPath: Path?, vararg args: String, transfor
|
||||
/**
|
||||
* Returns the configured pipenv executable or detects it automatically on the given [fileSystem].
|
||||
*/
|
||||
@Internal
|
||||
internal suspend fun <P : PathHolder> getPipEnvExecutable(fileSystem: FileSystem<P>): P? =
|
||||
PIPENV_TOOL.getToolExecutable(fileSystem, pathFromSdk = null)
|
||||
|
||||
/**
|
||||
* Returns the configured pipenv executable or detects it automatically.
|
||||
*/
|
||||
@Internal
|
||||
internal suspend fun getPipEnvExecutable(eel: EelApi = localEel): Path? =
|
||||
getPipEnvExecutable(EelFileSystem(eel))?.path
|
||||
|
||||
internal suspend fun runPipEnvWithSdk(sdk: Sdk, vararg args: String): PyResult<String> {
|
||||
val data = sdk.pySdkAdditionalData
|
||||
val workingDirectory = data.workingDirectory.takeIf { data.hasValidWorkingDirectory() }
|
||||
?: return PyResult.localizedError(PyBundle.message("python.sdk.project.working.directory.not.found"))
|
||||
val sdkHomePath = sdk.homePath
|
||||
?: return PyResult.localizedError(PySdkBundle.message("python.sdk.broken.configuration", sdk.name))
|
||||
|
||||
return when (data) {
|
||||
is PyTargetAwareAdditionalData -> {
|
||||
val targetConfig = data.targetEnvironmentConfiguration
|
||||
?: return PyResult.localizedError(PySdkBundle.message("python.sdk.broken.configuration", sdk.name))
|
||||
runPipEnvWithSdk(
|
||||
fileSystem = service<TargetFileSystemCache>().getOrCreate(targetConfig, PythonLanguageRuntimeConfiguration()),
|
||||
workingDirectory = workingDirectory,
|
||||
sdkHomePath = sdkHomePath,
|
||||
args = args,
|
||||
)
|
||||
}
|
||||
else -> runPipEnvWithSdk(
|
||||
fileSystem = workingDirectory.toEelFileSystem(),
|
||||
workingDirectory = workingDirectory,
|
||||
sdkHomePath = sdkHomePath,
|
||||
args = args,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <P : PathHolder> runPipEnvWithSdk(
|
||||
fileSystem: FileSystem<P>,
|
||||
workingDirectory: Path,
|
||||
sdkHomePath: String,
|
||||
vararg args: String,
|
||||
): PyResult<String> {
|
||||
val pythonPath = fileSystem.parsePath(sdkHomePath).getOr { return it }
|
||||
val pythonHomePath = fileSystem.resolvePythonHome(pythonPath)
|
||||
return runPipEnv(
|
||||
fileSystem = fileSystem,
|
||||
dirPath = workingDirectory,
|
||||
args = args,
|
||||
baseEnv = mapOf("VIRTUAL_ENV" to pythonHomePath.toString()),
|
||||
downloadConfig = PIPENV_PROJECT_DOWNLOAD_CONFIG.takeIf { args.firstOrNull() in PIPENV_PROJECT_MUTATING_COMMANDS },
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the pipenv environment under the modal progress window.
|
||||
*
|
||||
* The pipenv is associated with the first valid object from this list:
|
||||
*
|
||||
* 1. New project specified by [newProjectPath]
|
||||
* 2. Existing module specified by [module]
|
||||
* 3. Existing project specified by [project]
|
||||
* Sets up the pipenv environment for [moduleBasePath] and creates its SDK.
|
||||
*
|
||||
* @return the SDK for pipenv, not stored in the SDK table yet.
|
||||
*/
|
||||
@Internal
|
||||
internal suspend fun setupPipEnvSdkWithProgressReport(
|
||||
internal suspend fun <P : PathHolder> setupPipEnvSdkWithProgressReport(
|
||||
moduleBasePath: Path,
|
||||
basePythonBinaryPath: PythonBinary?,
|
||||
basePythonBinaryPath: P?,
|
||||
fileSystem: FileSystem<P>,
|
||||
pipenvExecutable: P?,
|
||||
installPackages: Boolean,
|
||||
targetPanelExtension: TargetPanelExtension? = null,
|
||||
): PyResult<Sdk> {
|
||||
val pythonExecutablePath = setUpPipEnv(moduleBasePath, basePythonBinaryPath, installPackages).getOr { return it }
|
||||
val pythonHomePath = setupPipEnv(
|
||||
projectPath = moduleBasePath,
|
||||
fileSystem = fileSystem,
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
basePythonBinaryPath = basePythonBinaryPath,
|
||||
installPackages = installPackages,
|
||||
).getOr { return it }
|
||||
val pythonBinaryPath = fileSystem.resolvePythonBinary(pythonHomePath)
|
||||
?: return PyResult.localizedError(PyBundle.message("python.sdk.cannot.setup.sdk", pythonHomePath))
|
||||
|
||||
return createSdk(
|
||||
pythonBinaryPath = PathHolder.Eel(pythonExecutablePath),
|
||||
sdkAdditionalData = PyPipEnvSdkAdditionalData(moduleBasePath)
|
||||
return fileSystem.setupSdk(
|
||||
project = null,
|
||||
pythonBinaryPath = pythonBinaryPath,
|
||||
sdkAdditionalData = PyPipEnvSdkAdditionalData(moduleBasePath),
|
||||
targetPanelExtension = targetPanelExtension,
|
||||
suggestedSdkName = null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -93,12 +163,26 @@ internal suspend fun setupPipEnvSdkWithProgressReport(
|
||||
*
|
||||
* @return the path to the pipenv environment.
|
||||
*/
|
||||
@Internal
|
||||
internal suspend fun setupPipEnv(
|
||||
projectPath: Path,
|
||||
basePythonBinaryPath: PythonBinary?,
|
||||
installPackages: Boolean,
|
||||
): PyResult<@SystemDependent String> {
|
||||
): PyResult<@SystemDependent String> =
|
||||
setupPipEnv(
|
||||
projectPath = projectPath,
|
||||
fileSystem = projectPath.toEelFileSystem(),
|
||||
pipenvExecutable = null,
|
||||
basePythonBinaryPath = basePythonBinaryPath?.let(PathHolder::Eel),
|
||||
installPackages = installPackages,
|
||||
).mapSuccess { it.toString() }
|
||||
|
||||
internal suspend fun <P : PathHolder> setupPipEnv(
|
||||
projectPath: Path,
|
||||
fileSystem: FileSystem<P>,
|
||||
pipenvExecutable: P?,
|
||||
basePythonBinaryPath: P?,
|
||||
installPackages: Boolean,
|
||||
): PyResult<P> {
|
||||
val pipfile = projectPath.resolve(PIP_FILE)
|
||||
|
||||
if (!pipfile.exists()) {
|
||||
@@ -111,22 +195,37 @@ internal suspend fun setupPipEnv(
|
||||
|
||||
when {
|
||||
installPackages -> {
|
||||
val pythonArgs = if (basePythonBinaryPath != null) listOf("--python", basePythonBinaryPath.pathString) else emptyList()
|
||||
val pythonArgs = if (basePythonBinaryPath != null) listOf("--python", basePythonBinaryPath.toString()) else emptyList()
|
||||
val command = pythonArgs + listOf("install", "--dev")
|
||||
runPipEnv(projectPath, *command.toTypedArray()).getOr { return it }
|
||||
runPipEnv(
|
||||
fileSystem = fileSystem,
|
||||
dirPath = projectPath,
|
||||
args = command.toTypedArray(),
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
downloadConfig = PIPENV_PROJECT_DOWNLOAD_CONFIG,
|
||||
).getOr { return it }
|
||||
}
|
||||
basePythonBinaryPath != null ->
|
||||
runPipEnv(projectPath, "--python", basePythonBinaryPath.pathString).getOr { return it }
|
||||
runPipEnv(
|
||||
fileSystem = fileSystem,
|
||||
dirPath = projectPath,
|
||||
"--python", basePythonBinaryPath.toString(),
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
downloadConfig = PIPENV_PROJECT_DOWNLOAD_CONFIG,
|
||||
).getOr { return it }
|
||||
else ->
|
||||
runPipEnv(projectPath, "run", "python", "-V").getOr { return it }
|
||||
runPipEnv(
|
||||
fileSystem = fileSystem,
|
||||
dirPath = projectPath,
|
||||
"run", "python", "-V",
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
).getOr { return it }
|
||||
}
|
||||
return runPipEnv(projectPath, "--venv")
|
||||
}
|
||||
|
||||
private suspend fun setUpPipEnv(moduleBasePath: Path, basePythonBinaryPath: PythonBinary?, installPackages: Boolean): PyResult<Path> {
|
||||
val pipEnv = setupPipEnv(moduleBasePath, basePythonBinaryPath, installPackages).getOr { return it }
|
||||
val pipEnvExecutablePathString = withContext(Dispatchers.IO) {
|
||||
VirtualEnvReader().findPythonInPythonRoot(Path.of(pipEnv))?.toString()
|
||||
} ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", pipEnv))
|
||||
return PyResult.success(Path.of(pipEnvExecutablePathString))
|
||||
val pythonHomePath = runPipEnv(
|
||||
fileSystem = fileSystem,
|
||||
dirPath = projectPath,
|
||||
"--venv",
|
||||
pipenvExecutable = pipenvExecutable,
|
||||
).getOr { return it }
|
||||
return fileSystem.parsePath(pythonHomePath.trim())
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import com.intellij.python.community.impl.pipenv.PipEnvPyTool
|
||||
import com.jetbrains.python.sdk.flavors.CPythonSdkFlavor
|
||||
import com.jetbrains.python.sdk.flavors.PyFlavorData
|
||||
import com.jetbrains.python.sdk.flavors.PythonFlavorProvider
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.Path
|
||||
import javax.swing.Icon
|
||||
|
||||
|
||||
internal object PyPipEnvSdkFlavor : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
@ApiStatus.Internal
|
||||
object PyPipEnvSdkFlavor : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
override fun getIcon(): Icon = PipEnvPyTool.getInstance().icon
|
||||
override fun getFlavorDataClass(): Class<PyFlavorData.Empty> = PyFlavorData.Empty::class.java
|
||||
|
||||
@@ -19,4 +21,4 @@ internal object PyPipEnvSdkFlavor : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
|
||||
internal class PyPipEnvSdkFlavorProvider : PythonFlavorProvider {
|
||||
override fun getFlavor(): PyPipEnvSdkFlavor = PyPipEnvSdkFlavor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,19 +5,14 @@ import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.util.PathUtil
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
|
||||
import com.jetbrains.python.sdk.pySdkAdditionalData
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
|
||||
/**
|
||||
* Tells if the SDK was added as a pipenv.
|
||||
*/
|
||||
internal val Sdk.isPipEnv: Boolean
|
||||
get() {
|
||||
if (!PythonSdkUtil.isPythonSdk(this)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return sdkAdditionalData is PyPipEnvSdkAdditionalData
|
||||
}
|
||||
get() = PythonSdkUtil.isPythonSdk(this) && pySdkAdditionalData.flavor == PyPipEnvSdkFlavor
|
||||
|
||||
@Internal
|
||||
fun suggestedSdkName(basePath: @NlsSafe String): @NlsSafe String = "Pipenv (${PathUtil.getFileName(basePath)})"
|
||||
fun suggestedSdkName(basePath: @NlsSafe String): @NlsSafe String = "Pipenv (${PathUtil.getFileName(basePath)})"
|
||||
|
||||
Reference in New Issue
Block a user