mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-82326: Preparation for it (WIP): support ExecError for targets.
SSH is now target-based and we can't use `EelPath` with it. So we now have two types of `ExecError.exe`. Test is going to be created as next commit GitOrigin-RevId: 6bc56eb9770caeb7ba32c8f43e6f374fcf5a3325
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4dc8c380e3
commit
4964cc3a7d
@@ -4,18 +4,45 @@ package com.jetbrains.python.errorProcessing
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.platform.eel.path.EelPath
|
||||
import com.intellij.platform.eel.path.EelPathException
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResult
|
||||
import com.intellij.platform.eel.provider.utils.EelProcessExecutionResultInfo
|
||||
import com.intellij.platform.eel.provider.utils.stderrString
|
||||
import com.intellij.platform.eel.provider.utils.stdoutString
|
||||
import com.jetbrains.python.PyCommunityBundle
|
||||
import org.jetbrains.annotations.Nls
|
||||
import kotlin.io.path.Path
|
||||
|
||||
/**
|
||||
* Exe might sit on eel (new one) or on target (legacy)
|
||||
*/
|
||||
interface Exe {
|
||||
companion object {
|
||||
fun fromString(path: String): Exe {
|
||||
try {
|
||||
return OnEel(Path(path).asEelPath())
|
||||
}
|
||||
catch (_: EelPathException) {
|
||||
return OnTarget(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class OnEel(val eelPath: EelPath) : Exe {
|
||||
override fun toString(): String = eelPath.toString()
|
||||
}
|
||||
|
||||
data class OnTarget(val path: String) : Exe {
|
||||
override fun toString(): String = path
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* External process error.
|
||||
*/
|
||||
class ExecError(
|
||||
val exe: EelPath,
|
||||
val exe: Exe,
|
||||
/**
|
||||
* I.e ['-v']
|
||||
*/
|
||||
|
||||
@@ -4,11 +4,9 @@ package com.jetbrains.python.packaging
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
import com.jetbrains.python.errorProcessing.*
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.io.IOException
|
||||
import kotlin.io.path.Path
|
||||
|
||||
/**
|
||||
* Wraps [PyError] for cases where [ExecutionException] is used.
|
||||
@@ -31,7 +29,7 @@ class PyExecutionException private constructor(
|
||||
additionalMessageToUser: @NlsContexts.DialogMessage String?,
|
||||
command: String,
|
||||
args: List<String>,
|
||||
): PyExecutionException = PyExecutionException(ExecError(Path(command).asEelPath(), args.toTypedArray(), ExecErrorReason.Timeout, additionalMessageToUser))
|
||||
): PyExecutionException = PyExecutionException(ExecError(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.Timeout, additionalMessageToUser))
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +63,7 @@ class PyExecutionException private constructor(
|
||||
args: List<String>,
|
||||
fixes: List<PyExecutionFix> = listOf<PyExecutionFix>(),
|
||||
) : this(
|
||||
pyError = ExecError(Path(command).asEelPath(), args.toTypedArray(), ExecErrorReason.CantStart(null, startException.localizedMessage), additionalMessage),
|
||||
pyError = ExecError(Exe.fromString(command), args.toTypedArray(), ExecErrorReason.CantStart(null, startException.localizedMessage), additionalMessage),
|
||||
fixes = fixes,
|
||||
ioException = startException)
|
||||
|
||||
@@ -84,7 +82,7 @@ class PyExecutionException private constructor(
|
||||
output: ProcessOutput,
|
||||
fixes: List<PyExecutionFix> = listOf<PyExecutionFix>(),
|
||||
) : this(
|
||||
pyError = ExecError(Path(command).asEelPath(), args.toTypedArray(), output.asExecutionFailed()),
|
||||
pyError = ExecError(Exe.fromString(command), args.toTypedArray(), output.asExecutionFailed()),
|
||||
fixes = fixes)
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -85,7 +85,7 @@ private suspend fun EelExecutableProcess.run(): PyExecResult<EelProcess> {
|
||||
|
||||
private fun EelExecutableProcess.failAsCantStart(executeProcessError: ExecuteProcessException): Result.Failure<ExecError> {
|
||||
return ExecError(
|
||||
exe = exe,
|
||||
exe = Exe.OnEel(exe),
|
||||
args = args.toTypedArray(),
|
||||
additionalMessageToUser = PyExecBundle.message("py.exec.start.error", description, executeProcessError.message, executeProcessError.errno),
|
||||
errorReason = ExecErrorReason.CantStart(executeProcessError.errno, executeProcessError.message)
|
||||
@@ -96,7 +96,7 @@ private suspend fun EelExecutableProcess.killProcessAndFailAsTimeout(eelProcess:
|
||||
eelProcess.kill()
|
||||
|
||||
return ExecError(
|
||||
exe = exe,
|
||||
exe = Exe.OnEel( exe),
|
||||
args = args.toTypedArray(),
|
||||
additionalMessageToUser = PyExecBundle.message("py.exec.timeout.error", description, timeout),
|
||||
errorReason = ExecErrorReason.Timeout
|
||||
@@ -109,7 +109,7 @@ private fun EelExecutableProcess.failAsExecutionFailed(processOutput: ExecErrorR
|
||||
}
|
||||
|
||||
return ExecError(
|
||||
exe = exe,
|
||||
exe = Exe.OnEel(exe),
|
||||
args = args.toTypedArray(),
|
||||
additionalMessageToUser = additionalMessage,
|
||||
errorReason = processOutput
|
||||
|
||||
+3
-2
@@ -13,6 +13,7 @@ import com.intellij.platform.testFramework.junit5.eel.params.api.TestApplication
|
||||
import com.intellij.python.community.execService.*
|
||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.Exe
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import com.jetbrains.python.getOrThrow
|
||||
import kotlinx.coroutines.*
|
||||
@@ -195,7 +196,7 @@ class ExecServiceShowCaseTest {
|
||||
is Result.Failure -> {
|
||||
assertFalse(sunny, "Unexpected failure ${result.error}")
|
||||
assertThat("Wrong message to user", result.error.message, CoreMatchers.containsString(messageToUser))
|
||||
assertEquals(shell, (result.error as ExecError).exe.asNioPath(), "Wrong exe")
|
||||
assertEquals(shell, (result.error.exe as Exe.OnEel).eelPath.asNioPath(), "Wrong exe")
|
||||
}
|
||||
is Result.Success -> {
|
||||
assertTrue(sunny, "Unexpected success")
|
||||
@@ -213,7 +214,7 @@ class ExecServiceShowCaseTest {
|
||||
is Result.Success -> fail("Execution of bad command should lead to an error")
|
||||
is Result.Failure -> {
|
||||
val err = (output.error as ExecError)
|
||||
assertEquals(binary, err.exe.asNioPath(), "Wrong command reported")
|
||||
assertEquals(binary, (err.exe as Exe.OnEel).eelPath.asNioPath(), "Wrong command reported")
|
||||
assertEquals("foo", err.args[0], "Wrong args reported")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
package com.jetbrains.python.packaging
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
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 java.io.IOException
|
||||
import kotlin.io.path.Path
|
||||
|
||||
/**
|
||||
* A temporary hack for some outdated code (see usages), do not use in a new code. Stay away from [PyExecutionException]
|
||||
@@ -22,7 +21,7 @@ internal fun PyExecutionException.copyWith(newCommand: String, newArgs: List<Str
|
||||
PyExecutionException(IOException(reason.cantExecProcessError), err.message, newCommand, newArgs, fixes)
|
||||
}
|
||||
ExecErrorReason.Timeout -> {
|
||||
PyExecutionException(ExecError(Path(newCommand).asEelPath(), newArgs.toTypedArray(), ExecErrorReason.Timeout, err.message))
|
||||
PyExecutionException(ExecError(Exe.fromString(newCommand), newArgs.toTypedArray(), ExecErrorReason.Timeout, err.message))
|
||||
}
|
||||
is ExecErrorReason.UnexpectedProcessTermination -> {
|
||||
val output = ProcessOutput(reason.stdoutString, reason.stderrString, reason.exitCode, false, false)
|
||||
|
||||
@@ -36,13 +36,15 @@ import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import kotlin.math.min
|
||||
|
||||
internal class PipPackageManagerEngine(
|
||||
|
||||
@ApiStatus.Internal
|
||||
class PipPackageManagerEngine(
|
||||
private val project: Project,
|
||||
private val sdk: Sdk,
|
||||
) : PythonPackageManagerEngine {
|
||||
override suspend fun installPackageCommand(installRequest: PythonPackageInstallRequest, options: List<String>): PyResult<Unit> {
|
||||
val manager = PythonPackageManager.forSdk(project, sdk)
|
||||
PipManagementInstaller(sdk, manager).installManagementIfNeeded()
|
||||
PipManagementInstaller(sdk, manager).installManagementIfNeeded()
|
||||
val result = runPackagingTool(
|
||||
operation = "install",
|
||||
arguments = installRequest.indexUrlIfApplicable() + options
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.webcore.packaging.PackageManagementServiceEx;
|
||||
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.ExecErrorReason;
|
||||
import com.jetbrains.python.packaging.*;
|
||||
@@ -35,7 +36,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -195,7 +195,7 @@ public class PyPackageManagementService extends PackageManagementServiceEx {
|
||||
extraArgs.add("-U");
|
||||
}
|
||||
final PyRequirement req = version == null
|
||||
? PyRequirementsKt.pyRequirement(packageName,null)
|
||||
? PyRequirementsKt.pyRequirement(packageName, null)
|
||||
: PyRequirementsKt.pyRequirement(packageName, PyRequirementRelation.EQ, version);
|
||||
|
||||
final PyPackageManagerUI ui = new PyPackageManagerUI(myProject, mySdk, new PyPackageManagerUI.Listener() {
|
||||
@@ -358,8 +358,8 @@ public class PyPackageManagementService extends PackageManagementServiceEx {
|
||||
}
|
||||
}
|
||||
|
||||
var fileName = e.getExe().getFileName();
|
||||
if (fileName.startsWith("pip") && sdk != null) {
|
||||
var fileName = e.getExe();
|
||||
if (fileName instanceof Exe.OnEel exeOnEel && exeOnEel.getEelPath().getFileName().startsWith("pip") && sdk != null) {
|
||||
return PySdkBundle.message("python.sdk.try.to.run.command.from.system.terminal", sdk.getHomePath());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user