cleanup [python]: Get rid of checkExistence in env checker

No need to perform environment check twice, first with checking the env
existence, and then without.

GitOrigin-RevId: cc49cc238b8b8a4ceabfd7d3757b06c62156deed
This commit is contained in:
Alexey Katsman
2026-01-29 13:25:49 +00:00
committed by intellij-monorepo-bot
parent 71cb91d1b6
commit 1c737661f5
6 changed files with 57 additions and 80 deletions
@@ -69,26 +69,17 @@ sealed interface EnvCheckerResult {
}
@ApiStatus.Internal
// TODO: Make internal after we drop WSL sdk configurator
suspend fun prepareSdkCreator(
envChecker: suspend (CheckExistence) -> EnvCheckerResult,
envChecker: suspend () -> EnvCheckerResult,
sdkCreator: (EnvExists) -> SdkCreator,
): CreateSdkInfo? {
var res = envChecker(true)
return when (res) {
return when (val res = envChecker()) {
is EnvCheckerResult.EnvFound -> CreateSdkInfo.ExistingEnv(
res.pythonInfo,
res.intentionName,
sdkCreator(true)
)
is EnvCheckerResult.EnvNotFound -> {
res = envChecker(false)
when (res) {
is EnvCheckerResult.EnvNotFound -> CreateSdkInfo.WillCreateEnv(res.intentionName, sdkCreator(false))
is EnvCheckerResult.EnvFound -> throw AssertionError("Env shouldn't exist if we didn't check for it")
is EnvCheckerResult.CannotConfigure -> null
}
}
is EnvCheckerResult.EnvNotFound -> CreateSdkInfo.WillCreateEnv(res.intentionName, sdkCreator(false))
is EnvCheckerResult.CannotConfigure -> null
}
}
@@ -59,14 +59,13 @@ internal class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExten
override val toolId: ToolId = CONDA_TOOL_ID
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkManageableEnv(module, it) }
) { envExists -> { createAndAddSdk(module, envExists) } }
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? = prepareSdkCreator(
{ checkManageableEnv(module) }
) { envExists -> { createAndAddSdk(module, envExists) } }
override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension? = null
private suspend fun checkManageableEnv(module: Module, checkExistence: CheckExistence): EnvCheckerResult =
private suspend fun checkManageableEnv(module: Module): EnvCheckerResult =
withBackgroundProgress(module.project, PyBundle.message("python.sdk.validating.environment")) {
val condaPath = withContext(Dispatchers.IO) {
suggestCondaPath()?.let { LocalFileSystem.getInstance().findFileByPath(it) }
@@ -75,16 +74,15 @@ internal class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExten
val intentionName = PyBundle.message("sdk.create.condaenv.suggestion")
val envNotFound = EnvCheckerResult.EnvNotFound(intentionName)
when {
canManage && checkExistence -> {
getCondaEnvIdentity(module, condaPath.path)?.let { env ->
val binaryToExec = BinOnEel(Path.of(condaPath.path))
CondaExecutor.getPythonInfo(binaryToExec, env).findEnvOrNull(intentionName)
} ?: envNotFound
if (canManage) {
val envExistenceResult = getCondaEnvIdentity(module, condaPath.path)?.let { env ->
val binaryToExec = BinOnEel(Path.of(condaPath.path))
CondaExecutor.getPythonInfo(binaryToExec, env).findEnvOrNull(intentionName)
}
canManage -> if (getEnvironmentYml(module) != null) envNotFound else EnvCheckerResult.CannotConfigure
else -> EnvCheckerResult.CannotConfigure
envExistenceResult ?: if (getEnvironmentYml(module) != null) envNotFound else EnvCheckerResult.CannotConfigure
}
else EnvCheckerResult.CannotConfigure
}
private suspend fun getEnvironmentYml(module: Module) = listOf(
@@ -30,17 +30,18 @@ internal class PyHatchSdkConfiguration : PyProjectTomlConfigurationExtension {
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, checkExistence, true) },
{ checkManageableEnv(module, true) },
) { envExists -> { createSdk(module, envExists) } }
override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? = prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, checkExistence, false) },
) { envExists -> { createSdk(module, envExists) } }
override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkManageableEnv(module, false) },
) { envExists -> { createSdk(module, envExists) } }
override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this
private suspend fun checkManageableEnv(
module: Module, checkExistence: CheckExistence, checkToml: CheckToml,
module: Module, checkToml: CheckToml,
): EnvCheckerResult = reportRawProgress {
it.text(PyBundle.message("sdk.set.up.hatch.project.analysis"))
val hatchService = module.getHatchService().getOr { return EnvCheckerResult.CannotConfigure }
@@ -48,17 +49,14 @@ internal class PyHatchSdkConfiguration : PyProjectTomlConfigurationExtension {
val intentionName = PyBundle.message("sdk.set.up.hatch.environment")
val envNotFound = EnvCheckerResult.EnvNotFound(intentionName)
when {
canManage && checkExistence -> {
val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull().orLogException(LOGGER)?.pythonVirtualEnvironment
when (defaultEnv) {
is PythonVirtualEnvironment.Existing -> EnvCheckerResult.EnvFound(defaultEnv.pythonInfo, intentionName)
is PythonVirtualEnvironment.NotExisting, null -> envNotFound
}
if (canManage) {
val defaultEnv = hatchService.findDefaultVirtualEnvironmentOrNull().orLogException(LOGGER)?.pythonVirtualEnvironment
when (defaultEnv) {
is PythonVirtualEnvironment.Existing -> EnvCheckerResult.EnvFound(defaultEnv.pythonInfo, intentionName)
is PythonVirtualEnvironment.NotExisting, null -> envNotFound
}
canManage -> envNotFound
else -> EnvCheckerResult.CannotConfigure
}
else EnvCheckerResult.CannotConfigure
}
/**
@@ -41,13 +41,13 @@ internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension {
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkManageableEnv(module, it) }
{ checkManageableEnv(module) }
) { { createAndAddSdk(module) } }
override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension? = null
private suspend fun checkManageableEnv(
module: Module, checkExistence: CheckExistence,
module: Module,
): EnvCheckerResult = withBackgroundProgress(module.project, PyBundle.message("python.sdk.validating.environment")) {
val pipfile = findAmongRoots(module, PipEnvFileHelper.PIP_FILE)?.name ?: return@withBackgroundProgress EnvCheckerResult.CannotConfigure
val pipEnvExecutable = getPipEnvExecutable() ?: return@withBackgroundProgress EnvCheckerResult.CannotConfigure
@@ -55,26 +55,23 @@ internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension {
val intentionName = PyBundle.message("sdk.create.pipenv.suggestion", pipfile)
val envNotFound = EnvCheckerResult.EnvNotFound(intentionName)
when {
canManage && checkExistence -> {
PropertiesComponent.getInstance().pipenvPath = pipEnvExecutable.pathString
val envPath = runPipEnv(
module.baseDir?.path?.toNioPathOrNull(),
"--venv",
transformer = ZeroCodeStdoutParserTransformer { PyResult.success(Path.of(it)) }
).successOrNull
val path = envPath?.resolvePythonBinary()
val envExists = path?.let {
LocalFileSystem.getInstance().refreshAndFindFileByPath(it.pathString) != null
} ?: false
if (envExists) {
path.findEnvOrNull(intentionName) ?: envNotFound
}
else envNotFound
if (canManage) {
PropertiesComponent.getInstance().pipenvPath = pipEnvExecutable.pathString
val envPath = runPipEnv(
module.baseDir?.path?.toNioPathOrNull(),
"--venv",
transformer = ZeroCodeStdoutParserTransformer { PyResult.success(Path.of(it)) }
).successOrNull
val path = envPath?.resolvePythonBinary()
val envExists = path?.let {
LocalFileSystem.getInstance().refreshAndFindFileByPath(it.pathString) != null
} ?: false
if (envExists) {
path.findEnvOrNull(intentionName) ?: envNotFound
}
canManage -> envNotFound
else -> EnvCheckerResult.CannotConfigure
else envNotFound
}
else EnvCheckerResult.CannotConfigure
}
private suspend fun createAndAddSdk(module: Module): PyResult<Sdk> {
@@ -41,18 +41,18 @@ internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension {
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, checkExistence, true) },
{ checkManageableEnv(module, true) },
) { { createPoetry(module) } }
override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, checkExistence, false) },
{ checkManageableEnv(module, false) },
) { { createPoetry(module) } }
override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this
private suspend fun checkManageableEnv(
module: Module, checkExistence: CheckExistence, checkToml: CheckToml,
module: Module, checkToml: CheckToml,
): EnvCheckerResult = reportRawProgress {
it.text(PyBundle.message("python.sdk.validating.environment"))
@@ -67,18 +67,15 @@ internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension {
val intentionName = PyBundle.message("sdk.set.up.poetry.environment")
val envNotFound = EnvCheckerResult.EnvNotFound(intentionName)
when {
canManage && checkExistence -> {
val basePath = module.baseDir?.path?.toNioPathOrNull()
runPoetry(basePath, "check", "--lock").getOr { return@reportRawProgress envNotFound }
val envPath = runPoetry(basePath, "env", "info", "-p")
.mapSuccess { it.toNioPathOrNull() }
.getOr { return@reportRawProgress envNotFound }
envPath?.resolvePythonBinary()?.findEnvOrNull(intentionName) ?: return@reportRawProgress envNotFound
}
canManage -> envNotFound
else -> EnvCheckerResult.CannotConfigure
if (canManage) {
val basePath = module.baseDir?.path?.toNioPathOrNull()
runPoetry(basePath, "check", "--lock").getOr { return@reportRawProgress envNotFound }
val envPath = runPoetry(basePath, "env", "info", "-p")
.mapSuccess { it.toNioPathOrNull() }
.getOr { return@reportRawProgress envNotFound }
envPath?.resolvePythonBinary()?.findEnvOrNull(intentionName) ?: envNotFound
}
else EnvCheckerResult.CannotConfigure
}
private suspend fun createPoetry(module: Module): PyResult<Sdk> =
@@ -33,12 +33,12 @@ internal class PyUvSdkConfiguration : PyProjectTomlConfigurationExtension {
override suspend fun checkEnvironmentAndPrepareSdkCreator(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, venvsInModule, checkExistence) }
{ checkManageableEnv(module, venvsInModule) }
) { envExists -> { createUv(module, venvsInModule, envExists) } }
override suspend fun createSdkWithoutPyProjectTomlChecks(module: Module, venvsInModule: List<PythonBinary>): CreateSdkInfo? =
prepareSdkCreator(
{ checkExistence -> checkManageableEnv(module, venvsInModule, checkExistence) }
{ checkManageableEnv(module, venvsInModule) }
) { envExists -> { createUv(module, venvsInModule, envExists) } }
override fun asPyProjectTomlSdkConfigurationExtension(): PyProjectTomlConfigurationExtension = this
@@ -55,14 +55,10 @@ internal class PyUvSdkConfiguration : PyProjectTomlConfigurationExtension {
private suspend fun checkManageableEnv(
module: Module,
venvsInModule: List<PythonBinary>,
checkExistence: CheckExistence,
): EnvCheckerResult {
getUvExecutable() ?: return EnvCheckerResult.CannotConfigure
val intentionName = PyBundle.message("sdk.set.up.uv.environment", module.name)
val envFound = if (checkExistence) getUvEnv(venvsInModule)?.findEnvOrNull(intentionName) else null
val envFound = getUvEnv(venvsInModule)?.findEnvOrNull(intentionName)
return envFound ?: EnvCheckerResult.EnvNotFound(intentionName)
}