mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-18 20:41:22 +07:00
Python: separate api and impl in ExecService
GitOrigin-RevId: b390c2c626fe14fc576da34de5b6ecd360bf6fd5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ad39be4f1a
commit
924a192984
@@ -0,0 +1,21 @@
|
||||
// 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.platform.eel.EelProcess
|
||||
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResult
|
||||
import com.intellij.platform.eel.provider.utils.awaitProcessResult
|
||||
import com.intellij.python.community.execService.CustomErrorMessage
|
||||
import com.intellij.python.community.execService.ProcessInteractiveHandler
|
||||
import com.intellij.python.community.execService.ProcessSemiInteractiveFun
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.mapError
|
||||
|
||||
internal class ProcessSemiInteractiveHandlerImpl<T>(private val code: ProcessSemiInteractiveFun<T>) : ProcessInteractiveHandler<T> {
|
||||
override suspend fun getResultFromProcess(process: EelProcess): Result<T, Pair<EelProcessExecutionResult, CustomErrorMessage?>> {
|
||||
val result = code(process.stdin, process.exitCode)
|
||||
val processOutput = process.awaitProcessResult()
|
||||
return result.mapError { customErrorMessage ->
|
||||
Pair(processOutput, customErrorMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,8 @@ package com.intellij.python.community.execService
|
||||
import com.intellij.platform.eel.EelProcess
|
||||
import com.intellij.platform.eel.channels.EelSendChannel
|
||||
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResult
|
||||
import com.intellij.platform.eel.provider.utils.awaitProcessResult
|
||||
import com.intellij.python.community.execService.impl.ProcessSemiInteractiveHandlerImpl
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.mapError
|
||||
import kotlinx.coroutines.Deferred
|
||||
import org.jetbrains.annotations.Nls
|
||||
import java.io.IOException
|
||||
@@ -19,7 +18,7 @@ typealias CustomErrorMessage = @Nls String
|
||||
|
||||
|
||||
/**
|
||||
* In most cases you need [ProcessSemiInteractiveHandler]
|
||||
* In most cases you need [processSemiInteractiveHandler]
|
||||
*/
|
||||
fun interface ProcessInteractiveHandler<T> {
|
||||
/**
|
||||
@@ -31,21 +30,13 @@ fun interface ProcessInteractiveHandler<T> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [ProcessInteractiveHandler], but you do not have to collect output by yourself. You only have access to stdout and exit code.
|
||||
* So, you can only *write* something to process.
|
||||
*/
|
||||
class ProcessSemiInteractiveHandler<T>(private val code: ProcessSemiInteractiveFun<T>) : ProcessInteractiveHandler<T> {
|
||||
override suspend fun getResultFromProcess(process: EelProcess): Result<T, Pair<EelProcessExecutionResult, CustomErrorMessage?>> {
|
||||
val result = code(process.stdin, process.exitCode)
|
||||
val processOutput = process.awaitProcessResult()
|
||||
return result.mapError { customErrorMessage ->
|
||||
Pair(processOutput, customErrorMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process stdout -> result
|
||||
*/
|
||||
typealias ProcessSemiInteractiveFun<T> = suspend (EelSendChannel<IOException>, Deferred<Int>) -> Result<T, CustomErrorMessage?>
|
||||
|
||||
/**
|
||||
* [ProcessInteractiveHandler], but you do not have to collect output by yourself. You only have access to stdout and exit code.
|
||||
* So, you can only *write* something to process.
|
||||
*/
|
||||
fun <T> processSemiInteractiveHandler(code: ProcessSemiInteractiveFun<T>): ProcessInteractiveHandler<T> = ProcessSemiInteractiveHandlerImpl(code)
|
||||
|
||||
@@ -13,18 +13,21 @@ import com.intellij.platform.testFramework.junit5.eel.params.api.EelSource
|
||||
import com.intellij.platform.testFramework.junit5.eel.params.api.TestApplicationWithEel
|
||||
import com.intellij.python.community.execService.ExecService
|
||||
import com.intellij.python.community.execService.ProcessInteractiveHandler
|
||||
import com.intellij.python.community.execService.ProcessSemiInteractiveHandler
|
||||
import com.intellij.python.community.execService.WhatToExec
|
||||
import com.intellij.python.community.execService.processSemiInteractiveHandler
|
||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.getOrThrow
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.condition.OS
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junitpioneer.jupiter.cartesian.CartesianTest
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
/**
|
||||
* How to use [ExecService].
|
||||
@@ -110,14 +113,13 @@ class ExecServiceShowCaseTest {
|
||||
}
|
||||
|
||||
@CartesianTest
|
||||
|
||||
fun testSemiInteractive(
|
||||
@EelSource eelHolder: EelHolder,
|
||||
@CartesianTest.Values(booleans = [true, false]) sunny: Boolean,
|
||||
): Unit = timeoutRunBlocking {
|
||||
val messageToUser = "abc123"
|
||||
val shell = eelHolder.eel.exec.getShell().first
|
||||
val result = ExecService().executeInteractive(WhatToExec.Binary(shell.asNioPath()), emptyList(), processInteractiveHandler = ProcessSemiInteractiveHandler<Unit> { channel, exitCode ->
|
||||
val result = ExecService().executeInteractive(WhatToExec.Binary(shell.asNioPath()), emptyList(), processInteractiveHandler = processSemiInteractiveHandler<Unit> { channel, exitCode ->
|
||||
channel.sendWholeText("exit\n").getOrThrow()
|
||||
assertEquals(0, exitCode.await(), "Wrong exit code")
|
||||
if (sunny) {
|
||||
|
||||
Reference in New Issue
Block a user