mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Python: Introduce API to get process from SDK via ExecService
Look `src/com/jetbrains/python/sdk/sdkExecApi.kt` for method that executes SDK and returns a process. See `PySdkOnTargetTest` as a usage example. Merge-request: IJ-MR-171740 Merged-by: Ilya Kazakevich <ilya.kazakevich@jetbrains.com> GitOrigin-RevId: a7e9b6995eba7ae1fa71019b370acca2d98738d2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b03577e03d
commit
ec7562bf07
@@ -38,17 +38,19 @@ sealed interface Exe {
|
||||
}
|
||||
}
|
||||
|
||||
typealias ExecError = ExecErrorImpl<*>
|
||||
|
||||
/**
|
||||
* External process error.
|
||||
*/
|
||||
class ExecError(
|
||||
class ExecErrorImpl<T : ExecErrorReason>(
|
||||
val exe: Exe,
|
||||
/**
|
||||
* I.e ['-v']
|
||||
*/
|
||||
val args: Array<out String>,
|
||||
|
||||
val errorReason: ExecErrorReason,
|
||||
val errorReason: T,
|
||||
/**
|
||||
* optional message to be displayed to the user: Why did we run this process. I.e "running pip to install package".
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,7 @@ class PyExecutionException private constructor(
|
||||
additionalMessageToUser: @NlsContexts.DialogMessage String?,
|
||||
command: String,
|
||||
args: List<String>,
|
||||
): PyExecutionException = PyExecutionException(ExecError(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.Timeout, additionalMessageToUser))
|
||||
): PyExecutionException = PyExecutionException(ExecErrorImpl(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.Timeout, additionalMessageToUser))
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class PyExecutionException private constructor(
|
||||
args: List<String>,
|
||||
fixes: List<PyExecutionFix> = listOf<PyExecutionFix>(),
|
||||
) : this(
|
||||
pyError = ExecError(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.CantStart(null, startException.localizedMessage), additionalMessage),
|
||||
pyError = ExecErrorImpl(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.CantStart(null, startException.localizedMessage), additionalMessage),
|
||||
fixes = fixes,
|
||||
ioException = startException)
|
||||
|
||||
@@ -82,7 +82,7 @@ class PyExecutionException private constructor(
|
||||
output: ProcessOutput,
|
||||
fixes: List<PyExecutionFix> = listOf<PyExecutionFix>(),
|
||||
) : this(
|
||||
pyError = ExecError(Exe.fromString(command), args.toTypedArray(), output.asExecutionFailed()),
|
||||
pyError = ExecErrorImpl(Exe.fromString(command), args.toTypedArray(), output.asExecutionFailed()),
|
||||
fixes = fixes)
|
||||
|
||||
/**
|
||||
|
||||
+28
-1
@@ -5,7 +5,8 @@ import com.intellij.platform.eel.channels.EelSendChannel
|
||||
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResult
|
||||
import com.intellij.python.community.execService.impl.ProcessSemiInteractiveHandlerImpl
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.errorProcessing.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.CheckReturnValue
|
||||
@@ -40,6 +41,18 @@ interface ExecService {
|
||||
options: ExecOptions = ExecOptions(),
|
||||
processInteractiveHandler: ProcessInteractiveHandler<T>,
|
||||
): PyResult<T>
|
||||
|
||||
/**
|
||||
* Execute process from [binary] with [args]. It is up to you to manage its lifecycle.
|
||||
* When bound to [scopeToBind] process will be destroyed once [scopeToBind] gets cancelled.
|
||||
*/
|
||||
@CheckReturnValue
|
||||
suspend fun executeGetProcess(
|
||||
binary: BinaryToExec,
|
||||
args: Args = Args(),
|
||||
scopeToBind: CoroutineScope? = null,
|
||||
options: ExecGetProcessOptions = ExecGetProcessOptions(),
|
||||
): Result<Process, ExecuteGetProcessError<*>>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,3 +85,17 @@ typealias ProcessSemiInteractiveFun<T> = suspend (EelSendChannel, Deferred<EelPr
|
||||
* So, you can only *write* something to process.
|
||||
*/
|
||||
fun <T> processSemiInteractiveHandler(pyProcessListener: PyProcessListener? = null, code: ProcessSemiInteractiveFun<T>): ProcessInteractiveHandler<T> = ProcessSemiInteractiveHandlerImpl(pyProcessListener, code)
|
||||
|
||||
|
||||
sealed class ExecuteGetProcessError<T : PyError>(val pyError: T) {
|
||||
/**
|
||||
* Failed to create environment for process (i.e. failed to start docker)
|
||||
*/
|
||||
class EnvironmentError internal constructor(pyError: MessageError) : ExecuteGetProcessError<MessageError>(pyError)
|
||||
|
||||
/**
|
||||
* Process couldn't be started
|
||||
*/
|
||||
class CanStart internal constructor(pyError: ExecErrorImpl<ExecErrorReason.CantStart>) : ExecuteGetProcessError<ExecErrorImpl<ExecErrorReason.CantStart>>(pyError)
|
||||
}
|
||||
|
||||
|
||||
@@ -169,12 +169,27 @@ object ZeroCodeStdoutTransformer : ProcessOutputTransformer<String> {
|
||||
* @property[env] Environment variables to be applied with the process run
|
||||
* @property[timeout] Process gets killed after this timeout
|
||||
* @property[processDescription] optional description to be displayed to user
|
||||
* [tty] Much like [com.intellij.platform.eel.EelExecApi.Pty]
|
||||
*/
|
||||
data class ExecOptions(
|
||||
val env: Map<String, String> = emptyMap(),
|
||||
val processDescription: @Nls String? = null,
|
||||
override val env: Map<String, String> = emptyMap(),
|
||||
override val processDescription: @Nls String? = null,
|
||||
val timeout: Duration = 5.minutes,
|
||||
)
|
||||
override val tty: TtySize? = null,
|
||||
) : ExecOptionsBase
|
||||
|
||||
|
||||
/**
|
||||
* Options for [ExecService.executeGetProcess]
|
||||
* See [ExecOptions]
|
||||
*/
|
||||
data class ExecGetProcessOptions(
|
||||
override val env: Map<String, String> = emptyMap(),
|
||||
override val processDescription: @Nls String? = null,
|
||||
override val tty: TtySize? = null,
|
||||
) : ExecOptionsBase
|
||||
|
||||
data class TtySize(val rows: UShort, val cols: UShort)
|
||||
|
||||
/**
|
||||
* See [Args.addLocalFile]
|
||||
|
||||
+43
-13
@@ -1,14 +1,18 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.community.execService.impl
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.python.community.execService.*
|
||||
import com.intellij.python.community.execService.impl.processLaunchers.*
|
||||
import com.intellij.python.community.execService.impl.processLaunchers.LaunchRequest
|
||||
import com.intellij.python.community.execService.impl.processLaunchers.ProcessLauncher
|
||||
import com.intellij.python.community.execService.impl.processLaunchers.createProcessLauncherOnEel
|
||||
import com.intellij.python.community.execService.impl.processLaunchers.createProcessLauncherOnTarget
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.errorProcessing.failure
|
||||
import com.jetbrains.python.errorProcessing.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.withTimeout
|
||||
@@ -17,13 +21,34 @@ import org.jetbrains.annotations.Nls
|
||||
|
||||
internal object ExecServiceImpl : ExecService {
|
||||
|
||||
override suspend fun <T> executeAdvanced(binary: BinaryToExec, args: Args, options: ExecOptions, processInteractiveHandler: ProcessInteractiveHandler<T>): PyResult<T> {
|
||||
override suspend fun executeGetProcess(binary: BinaryToExec, args: Args, scopeToBind: CoroutineScope?, options: ExecGetProcessOptions): Result<Process, ExecuteGetProcessError<*>> {
|
||||
val launcher = create(binary, args, options, scopeToBind).getOr { return it }
|
||||
val process = launcher.start().getOr {
|
||||
val createExecError = launcher.createExecError(options.processDescription ?: "", it.error).error
|
||||
return Result.failure(ExecuteGetProcessError.CanStart(createExecError))
|
||||
}
|
||||
return Result.success(process)
|
||||
}
|
||||
|
||||
return coroutineScope {
|
||||
val request = LaunchRequest(this, args, options.env)
|
||||
val processLauncher: ProcessLauncher = when (binary) {
|
||||
private suspend fun create(binary: BinaryToExec, args: Args, options: ExecOptionsBase, scopeToBind: CoroutineScope? = null): Result<ProcessLauncher, ExecuteGetProcessError.EnvironmentError> {
|
||||
val scope = scopeToBind ?: ApplicationManager.getApplication().service<MyService>().scope
|
||||
val request = LaunchRequest(scope, args, options.env, options.tty)
|
||||
return Result.success(
|
||||
when (binary) {
|
||||
is BinOnEel -> createProcessLauncherOnEel(binary, request)
|
||||
is BinOnTarget -> createProcessLauncherOnTarget(binary, request).getOr { return@coroutineScope it }
|
||||
is BinOnTarget -> createProcessLauncherOnTarget(binary, request).getOr {
|
||||
options.processDescription?.let { message ->
|
||||
it.error.pyError.addMessage(message) // TODO: 18n
|
||||
}
|
||||
return it
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override suspend fun <T> executeAdvanced(binary: BinaryToExec, args: Args, options: ExecOptions, processInteractiveHandler: ProcessInteractiveHandler<T>): PyResult<T> {
|
||||
return coroutineScope {
|
||||
val processLauncher = create(binary, args, options, this).getOr {
|
||||
return@coroutineScope it.asPyError()
|
||||
}
|
||||
|
||||
val description = options.processDescription
|
||||
@@ -66,8 +91,8 @@ internal object ExecServiceImpl : ExecService {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ProcessLauncher.createExecError(messageToUser: @Nls String, errorReason: ExecErrorReason): Result.Failure<ExecError> =
|
||||
ExecError(
|
||||
private fun <T : ExecErrorReason> ProcessLauncher.createExecError(messageToUser: @Nls String, errorReason: T): Result.Failure<ExecErrorImpl<T>> =
|
||||
ExecErrorImpl(
|
||||
exe = exeForError,
|
||||
args = args.toTypedArray(),
|
||||
additionalMessageToUser = messageToUser,
|
||||
@@ -75,7 +100,12 @@ private fun ProcessLauncher.createExecError(messageToUser: @Nls String, errorRea
|
||||
).logAndFail()
|
||||
|
||||
|
||||
private fun ExecError.logAndFail(): Result.Failure<ExecError> {
|
||||
private fun <T : ExecErrorReason> ExecErrorImpl<T>.logAndFail(): Result.Failure<ExecErrorImpl<T>> {
|
||||
fileLogger().warn(message)
|
||||
return failure(this)
|
||||
}
|
||||
|
||||
@Service
|
||||
private class MyService(val scope: CoroutineScope)
|
||||
|
||||
private fun Result.Failure<ExecuteGetProcessError<*>>.asPyError(): Result.Failure<PyError> = PyResult.failure(this.error.pyError)
|
||||
+3
-1
@@ -4,6 +4,7 @@ package com.intellij.python.community.execService.impl.processLaunchers
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.platform.eel.provider.utils.ProcessFunctions
|
||||
import com.intellij.python.community.execService.Args
|
||||
import com.intellij.python.community.execService.TtySize
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.Exe
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason
|
||||
@@ -31,4 +32,5 @@ internal data class LaunchRequest(
|
||||
val scopeToBind: CoroutineScope,
|
||||
val args: Args,
|
||||
val env: Map<String, String>,
|
||||
)
|
||||
val usePty: TtySize?
|
||||
)
|
||||
|
||||
+5
-1
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.community.execService.impl.processLaunchers
|
||||
|
||||
import com.intellij.platform.eel.EelExecApi
|
||||
import com.intellij.platform.eel.EelProcess
|
||||
import com.intellij.platform.eel.ExecuteProcessException
|
||||
import com.intellij.platform.eel.path.EelPath
|
||||
@@ -9,6 +10,7 @@ import com.intellij.platform.eel.provider.utils.EelPathUtils
|
||||
import com.intellij.platform.eel.provider.utils.ProcessFunctions
|
||||
import com.intellij.platform.eel.spawnProcess
|
||||
import com.intellij.python.community.execService.BinOnEel
|
||||
import com.intellij.python.community.execService.TtySize
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.Exe
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason
|
||||
@@ -28,7 +30,7 @@ internal suspend fun createProcessLauncherOnEel(binOnEel: BinOnEel, launchReques
|
||||
return ProcessLauncher(
|
||||
exeForError = Exe.OnEel(exePath),
|
||||
args = args,
|
||||
processCommands = EelProcessCommands(launchRequest.scopeToBind, binOnEel, exePath, args, launchRequest.env)
|
||||
processCommands = EelProcessCommands(launchRequest.scopeToBind, binOnEel, exePath, args, launchRequest.env, launchRequest.usePty)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -38,6 +40,7 @@ private class EelProcessCommands(
|
||||
private val path: EelPath,
|
||||
private val args: List<String>,
|
||||
private val env: Map<String, String>,
|
||||
private val tty: TtySize?,
|
||||
) : ProcessCommands {
|
||||
private var eelProcess: EelProcess? = null
|
||||
|
||||
@@ -56,6 +59,7 @@ private class EelProcessCommands(
|
||||
.args(args)
|
||||
.env(env)
|
||||
.workingDirectory(workDir?.asEelPath())
|
||||
.interactionOptions(if (tty != null) EelExecApi.Pty(tty.cols.toInt(), tty.rows.toInt()) else null)
|
||||
.eelIt()
|
||||
this.eelProcess = eelProcess
|
||||
return Result.success(eelProcess.convertToJavaProcess())
|
||||
|
||||
+20
-8
@@ -4,18 +4,20 @@
|
||||
package com.intellij.python.community.execService.impl.processLaunchers
|
||||
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.process.LocalPtyOptions
|
||||
import com.intellij.execution.target.*
|
||||
import com.intellij.execution.target.local.LocalTargetEnvironmentRequest
|
||||
import com.intellij.execution.target.local.LocalTargetPtyOptions
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.platform.eel.provider.utils.ProcessFunctions
|
||||
import com.intellij.platform.eel.provider.utils.bindProcessToScopeImpl
|
||||
import com.intellij.python.community.execService.BinOnTarget
|
||||
import com.intellij.python.community.execService.ExecuteGetProcessError
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.Exe
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason
|
||||
import com.jetbrains.python.errorProcessing.MessageError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -25,7 +27,7 @@ import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
private val logger = fileLogger()
|
||||
|
||||
internal suspend fun createProcessLauncherOnTarget(binOnTarget: BinOnTarget, launchRequest: LaunchRequest): PyResult<ProcessLauncher> = withContext(Dispatchers.IO) {
|
||||
internal suspend fun createProcessLauncherOnTarget(binOnTarget: BinOnTarget, launchRequest: LaunchRequest): Result<ProcessLauncher, ExecuteGetProcessError.EnvironmentError> = withContext(Dispatchers.IO) {
|
||||
val target = binOnTarget.target
|
||||
|
||||
val request = if (target != null) {
|
||||
@@ -44,19 +46,29 @@ internal suspend fun createProcessLauncherOnTarget(binOnTarget: BinOnTarget, lau
|
||||
}
|
||||
catch (e: ExecutionException) {
|
||||
fileLogger().warn("Failed to start $target", e) // TODO: i18n
|
||||
return@withContext Result.failure(MessageError("Failed to start environment due to ${e.localizedMessage}"))
|
||||
return@withContext Result.failure(ExecuteGetProcessError.EnvironmentError(MessageError("Failed to start environment due to ${e.localizedMessage}")))
|
||||
}
|
||||
val args = launchRequest.args.getArgs { localFile ->
|
||||
targetEnv.getTargetPaths(localFile.pathString).first()
|
||||
}
|
||||
val exePath: FullPathOnTarget
|
||||
val cmdLine = TargetedCommandLineBuilder(request).also {
|
||||
binOnTarget.configureTargetCmdLine(it)
|
||||
val cmdLine = TargetedCommandLineBuilder(request).also {commandLineBuilder ->
|
||||
binOnTarget.configureTargetCmdLine(commandLineBuilder)
|
||||
// exe path is always fixed (pre-presolved) promise. It can't be obtained directly because of Targets API limitation
|
||||
exePath = it.exePath.localValue.blockingGet(1000) ?: error("Exe path not set: $binOnTarget is broken")
|
||||
it.addParameters(args)
|
||||
exePath = commandLineBuilder.exePath.localValue.blockingGet(1000) ?: error("Exe path not set: $binOnTarget is broken")
|
||||
launchRequest.usePty?.let {
|
||||
val ptyOptions = LocalPtyOptions
|
||||
.defaults()
|
||||
.builder()
|
||||
.initialRows(it.rows.toInt())
|
||||
.initialColumns(it.cols.toInt())
|
||||
.build()
|
||||
commandLineBuilder.ptyOptions = LocalTargetPtyOptions(ptyOptions)
|
||||
}
|
||||
|
||||
commandLineBuilder.addParameters(args)
|
||||
for ((k, v) in launchRequest.env) {
|
||||
it.addEnvironmentVariable(k, v)
|
||||
commandLineBuilder.addEnvironmentVariable(k, v)
|
||||
}
|
||||
}.build()
|
||||
return@withContext Result.success(ProcessLauncher(exeForError = Exe.OnTarget(exePath), args = args, processCommands = TargetProcessCommands(launchRequest.scopeToBind, exePath, targetEnv, cmdLine)))
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.community.execService
|
||||
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
internal sealed interface ExecOptionsBase {
|
||||
val env: Map<String, String>
|
||||
val processDescription: @Nls String?
|
||||
val tty: TtySize?
|
||||
}
|
||||
@@ -4,10 +4,7 @@ package com.jetbrains.python.packaging
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.platform.eel.provider.utils.stderrString
|
||||
import com.intellij.platform.eel.provider.utils.stdoutString
|
||||
import com.jetbrains.python.errorProcessing.Exe
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason
|
||||
import com.jetbrains.python.errorProcessing.MessageError
|
||||
import com.jetbrains.python.errorProcessing.*
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
@@ -21,7 +18,7 @@ internal fun PyExecutionException.copyWith(newCommand: String, newArgs: List<Str
|
||||
PyExecutionException(IOException(reason.cantExecProcessError), err.message, newCommand, newArgs, fixes)
|
||||
}
|
||||
ExecErrorReason.Timeout -> {
|
||||
PyExecutionException(ExecError(Exe.fromString(newCommand), newArgs.toTypedArray(), ExecErrorReason.Timeout, err.message))
|
||||
PyExecutionException(ExecErrorImpl(Exe.fromString(newCommand), newArgs.toTypedArray(), ExecErrorReason.Timeout, err.message))
|
||||
}
|
||||
is ExecErrorReason.UnexpectedProcessTermination -> {
|
||||
val output = ProcessOutput(reason.stdoutString, reason.stderrString, reason.exitCode, false, false)
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock;
|
||||
import com.intellij.util.net.HttpConfigurable;
|
||||
import com.jetbrains.python.PyPsiPackageUtil;
|
||||
import com.jetbrains.python.PySdkBundle;
|
||||
import com.jetbrains.python.errorProcessing.ExecError;
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorImpl;
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason;
|
||||
import com.jetbrains.python.packaging.common.PythonPackage;
|
||||
import com.jetbrains.python.packaging.pip.PipParseUtils;
|
||||
@@ -134,7 +134,7 @@ public abstract class PyPackageManagerImplBase extends PyPackageManager {
|
||||
}
|
||||
catch (PyExecutionException e) {
|
||||
var pyError = e.getPyError();
|
||||
if (pyError instanceof ExecError error) {
|
||||
if (pyError instanceof ExecErrorImpl<?> error) {
|
||||
var errorReason = error.getErrorReason();
|
||||
if (errorReason instanceof ExecErrorReason.UnexpectedProcessTermination unexpectedProcessTermination) {
|
||||
int exitCode = unexpectedProcessTermination.getExitCode();
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.intellij.webcore.packaging.RepoPackage;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PySdkBundle;
|
||||
import com.jetbrains.python.errorProcessing.Exe;
|
||||
import com.jetbrains.python.errorProcessing.ExecError;
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorImpl;
|
||||
import com.jetbrains.python.errorProcessing.ExecErrorReason;
|
||||
import com.jetbrains.python.packaging.*;
|
||||
import com.jetbrains.python.packaging.PyPIPackageUtil.PackageDetails;
|
||||
@@ -320,7 +320,7 @@ public class PyPackageManagementService extends PackageManagementServiceEx {
|
||||
@Nullable Sdk sdk,
|
||||
@Nullable String packageName) {
|
||||
if (e instanceof PyExecutionException pyExecEx &&
|
||||
pyExecEx.getPyError() instanceof ExecError execError &&
|
||||
pyExecEx.getPyError() instanceof ExecErrorImpl<?> execError &&
|
||||
execError.getErrorReason() instanceof ExecErrorReason.UnexpectedProcessTermination execFailed) {
|
||||
var stdout = getStdoutString(execFailed);
|
||||
var stderr = getStderrString(execFailed);
|
||||
@@ -343,7 +343,7 @@ public class PyPackageManagementService extends PackageManagementServiceEx {
|
||||
private static @Nullable @DetailedDescription String findErrorSolution(@NotNull PyExecutionException executionException,
|
||||
@Nullable String cause,
|
||||
@Nullable Sdk sdk) {
|
||||
if (executionException.getPyError() instanceof ExecError e) {
|
||||
if (executionException.getPyError() instanceof ExecErrorImpl<?> e) {
|
||||
|
||||
if (cause != null) {
|
||||
if (StringUtil.containsIgnoreCase(cause, "SyntaxError")) {
|
||||
|
||||
@@ -5,8 +5,10 @@ import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.python.community.execService.*
|
||||
import com.intellij.python.community.execService.python.HelperName
|
||||
import com.intellij.python.community.execService.python.addHelper
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.target.PyTargetAwareAdditionalData
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.CheckReturnValue
|
||||
|
||||
@@ -48,6 +50,17 @@ suspend fun ExecService.executeHelper(
|
||||
): PyResult<String> =
|
||||
execGetStdout(sdk, Args().addHelper(helper).addArgs(helperArgs), options, procListener)
|
||||
|
||||
|
||||
// See function it calls for more info
|
||||
@ApiStatus.Internal
|
||||
@CheckReturnValue
|
||||
suspend fun ExecService.executeGetProcess(
|
||||
sdk: Sdk,
|
||||
args: Args = Args(),
|
||||
scopeToBind: CoroutineScope? = null,
|
||||
options: ExecGetProcessOptions = ExecGetProcessOptions(),
|
||||
): Result<Process, ExecuteGetProcessError<*>> = executeGetProcess(sdk.asBinToExecute(), args, scopeToBind, options)
|
||||
|
||||
/**
|
||||
* Converts SDK to [BinOnTarget] to be used by [ExecService]
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user