mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-26 19:06:24 +07:00
Python: refactor PyError hierarchy, migrate to PyResult.
DO: For upper-level (public) API use `PyResult`. (Optionally) for low-level APIs inside your modules use python `Result<S, E>`. Represent errors as `PyError` whenever possible. Report `PyError` to `ErrorSink` at the top of your code. DON'T: Use `kotlin.Result` Use `PyExecutionException` Use any exception to represent user errors. GitOrigin-RevId: 4ecf69e1fae8be9192cd33b90e0147c725a98964
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d366245171
commit
803e270d45
@@ -9,8 +9,8 @@ import com.intellij.python.hatch.PyHatchBundle
|
||||
import com.intellij.python.hatch.runtime.HatchConstants
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import io.github.z4kn4fein.semver.Version
|
||||
import io.github.z4kn4fein.semver.VersionFormatException
|
||||
import java.nio.file.Path
|
||||
@@ -18,7 +18,7 @@ import java.nio.file.Path
|
||||
/**
|
||||
* Handles hatch-specific errors, runs [transformer] only on outputs with codes 0 or 1 without tracebacks.
|
||||
*/
|
||||
private suspend fun <T> HatchRuntime.executeAndHandleErrors(vararg arguments: String, transformer: ProcessOutputTransformer<T>): Result<T, ExecException> {
|
||||
private suspend fun <T> HatchRuntime.executeAndHandleErrors(vararg arguments: String, transformer: ProcessOutputTransformer<T>): Result<T, ExecError> {
|
||||
val errorHandlerTransformer: ProcessOutputTransformer<T> = { output ->
|
||||
when {
|
||||
output.exitCode !in 0..1 -> Result.failure(null)
|
||||
@@ -38,7 +38,7 @@ private suspend fun <T> HatchRuntime.executeAndMatch(
|
||||
expectedOutput: Regex,
|
||||
outputContentSupplier: (ProcessOutput) -> String = ProcessOutput::getStdout,
|
||||
transformer: (MatchResult) -> Result<T, @NlsSafe String?>,
|
||||
): Result<T, ExecException> {
|
||||
): Result<T, ExecError> {
|
||||
return this.executeAndHandleErrors(*arguments) { processOutput ->
|
||||
if (processOutput.exitCode != 0) return@executeAndHandleErrors Result.failure(null)
|
||||
|
||||
@@ -57,11 +57,11 @@ sealed class HatchCommand(private val command: Array<String>, protected val runt
|
||||
@Suppress("unused")
|
||||
constructor(command: String, runtime: HatchRuntime) : this(arrayOf(command), runtime)
|
||||
|
||||
protected suspend fun <T> executeAndHandleErrors(vararg arguments: String, transformer: ProcessOutputTransformer<T>): Result<T, ExecException> {
|
||||
protected suspend fun <T> executeAndHandleErrors(vararg arguments: String, transformer: ProcessOutputTransformer<T>): Result<T, ExecError> {
|
||||
return runtime.executeAndHandleErrors(*command, *arguments, transformer = transformer)
|
||||
}
|
||||
|
||||
protected suspend fun <T> executeAndMatch(vararg arguments: String, expectedOutput: Regex, transformer: (MatchResult) -> Result<T, @NlsSafe String?>): Result<T, ExecException> {
|
||||
protected suspend fun <T> executeAndMatch(vararg arguments: String, expectedOutput: Regex, transformer: (MatchResult) -> Result<T, @NlsSafe String?>): Result<T, ExecError> {
|
||||
return runtime.executeAndMatch(*command, *arguments, expectedOutput = expectedOutput, transformer = transformer)
|
||||
}
|
||||
}
|
||||
@@ -70,12 +70,12 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Build a project
|
||||
*/
|
||||
fun build(): Result<Unit, ExecException> = TODO()
|
||||
fun build(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* Remove build artifacts
|
||||
*/
|
||||
fun clean(): Result<Unit, ExecException> = TODO()
|
||||
fun clean(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* Manage the config file
|
||||
@@ -95,7 +95,7 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Format and lint source code
|
||||
*/
|
||||
fun fmt(): Result<Unit, ExecException> = TODO()
|
||||
fun fmt(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* Create or initialize a project.
|
||||
@@ -114,7 +114,7 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
*
|
||||
* @param[initExistingProject] Initialize an existing project
|
||||
*/
|
||||
suspend fun new(projectName: String, location: Path? = null, initExistingProject: Boolean = false): Result<String, PyError> {
|
||||
suspend fun new(projectName: String, location: Path? = null, initExistingProject: Boolean = false): PyResult<String> {
|
||||
val options = listOf(
|
||||
initExistingProject to "--init",
|
||||
true to projectName,
|
||||
@@ -136,7 +136,7 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Publish build artifacts
|
||||
*/
|
||||
fun publish(): Result<Unit, ExecException> = TODO()
|
||||
fun publish(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* Manage Python installations
|
||||
@@ -146,7 +146,7 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Run commands within project environments
|
||||
*/
|
||||
suspend fun run(envName: String, vararg command: String): Result<String, ExecException> {
|
||||
suspend fun run(envName: String, vararg command: String): Result<String, ExecError> {
|
||||
val envRuntime = runtime.withEnv(HatchConstants.AppEnvVars.ENV to envName)
|
||||
return envRuntime.executeAndHandleErrors("run", *command) { output ->
|
||||
val scenario = output.stderr.trim()
|
||||
@@ -170,14 +170,14 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Enter a shell within a project's environment
|
||||
*/
|
||||
fun shell(): Result<Unit, ExecException> = TODO()
|
||||
fun shell(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
data class HatchStatus(val project: String, val location: Path, val config: Path)
|
||||
|
||||
/**
|
||||
* Show information about the current environment
|
||||
*/
|
||||
suspend fun status(): Result<HatchStatus, ExecException> {
|
||||
suspend fun status(): Result<HatchStatus, ExecError> {
|
||||
val expectedOutput = """^\[Project] - (.*)\n\[Location] - (.*)\n\[Config] - (.*)\n$""".toRegex()
|
||||
|
||||
return runtime.executeAndMatch("status", expectedOutput = expectedOutput, outputContentSupplier = { it.stderr }) { matchResult ->
|
||||
@@ -194,14 +194,14 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
/**
|
||||
* Run tests
|
||||
*/
|
||||
fun test(): Result<Unit, ExecException> = TODO()
|
||||
fun test(): Result<Unit, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* View a project's version.
|
||||
*
|
||||
* @return Project Version
|
||||
*/
|
||||
suspend fun getVersion(): Result<Version, ExecException> {
|
||||
suspend fun getVersion(): Result<Version, ExecError> {
|
||||
return runtime.executeAndHandleErrors("version") { processOutput ->
|
||||
val output = processOutput.takeIf { it.exitCode == 0 }?.stdout?.trim()
|
||||
?: return@executeAndHandleErrors Result.failure(null)
|
||||
@@ -219,7 +219,7 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
*
|
||||
* @return OldVersion to NewVersion as Pair
|
||||
*/
|
||||
suspend fun setVersion(desiredVersion: String): Result<Pair<Version, Version>, PyError> {
|
||||
suspend fun setVersion(desiredVersion: String): PyResult<Pair<Version, Version>> {
|
||||
val expectedOutput = """^Old: (.*)\nNew: (.*)\n$""".toRegex()
|
||||
|
||||
return runtime.executeAndMatch("version", desiredVersion, expectedOutput = expectedOutput, outputContentSupplier = { it.stderr }) { matchResult ->
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.intellij.python.hatch.cli
|
||||
import com.intellij.python.community.execService.ZeroCodeStdoutTransformer
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
|
||||
/**
|
||||
* Manage environment dependencies
|
||||
@@ -13,28 +13,28 @@ class HatchConfig(runtime: HatchRuntime) : HatchCommand("config", runtime) {
|
||||
/**
|
||||
* Open the config location in your file manager
|
||||
*/
|
||||
suspend fun explore(): Result<String, ExecException> {
|
||||
suspend fun explore(): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("explore", transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the location of the config file
|
||||
*/
|
||||
suspend fun find(): Result<String, ExecException> {
|
||||
suspend fun find(): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("find", transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the config file to default settings
|
||||
*/
|
||||
suspend fun restore(): Result<String, ExecException> {
|
||||
suspend fun restore(): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("restore", transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign values to config file entries
|
||||
*/
|
||||
suspend fun set(key: String, value: String): Result<String, ExecException> {
|
||||
suspend fun set(key: String, value: String): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("set", key, value, transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class HatchConfig(runtime: HatchRuntime) : HatchCommand("config", runtime) {
|
||||
*
|
||||
* @param all Do not scrub secret fields
|
||||
*/
|
||||
suspend fun show(all: Boolean? = null): Result<String, ExecException> {
|
||||
suspend fun show(all: Boolean? = null): Result<String, ExecError> {
|
||||
val options = listOf(all to "--all").makeOptions()
|
||||
return executeAndHandleErrors("show", *options, transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class HatchConfig(runtime: HatchRuntime) : HatchCommand("config", runtime) {
|
||||
/**
|
||||
* Update the config file with any new fields
|
||||
*/
|
||||
suspend fun update(): Result<String, ExecException> {
|
||||
suspend fun update(): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("update", transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ package com.intellij.python.hatch.cli
|
||||
import com.intellij.python.community.execService.ZeroCodeStdoutTransformer
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
|
||||
enum class Scope(val options: Array<String>) {
|
||||
All(emptyArray()),
|
||||
@@ -19,7 +19,7 @@ class HatchDep(runtime: HatchRuntime) : HatchCommand("dep", runtime) {
|
||||
/**
|
||||
* Output a hash of the currently defined dependencies
|
||||
**/
|
||||
suspend fun hash(scope: Scope = Scope.All): Result<String, ExecException> {
|
||||
suspend fun hash(scope: Scope = Scope.All): Result<String, ExecError> {
|
||||
return executeAndHandleErrors("hash", *scope.options, transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class HatchDepShow(runtime: HatchRuntime) : HatchCommand(arrayOf("dep", "show"),
|
||||
*
|
||||
* @param features only show the dependencies of the specified features
|
||||
*/
|
||||
suspend fun requirements(scope: Scope = Scope.All, features: List<String>? = null): Result<String, ExecException> {
|
||||
suspend fun requirements(scope: Scope = Scope.All, features: List<String>? = null): Result<String, ExecError> {
|
||||
val options = features?.flatMap { listOf("--feature", it) }?.toTypedArray() ?: arrayOf("--all")
|
||||
return executeAndHandleErrors("requirements", *scope.options, *options, transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class HatchDepShow(runtime: HatchRuntime) : HatchCommand(arrayOf("dep", "show"),
|
||||
/**
|
||||
* Enumerate dependencies in a tabular format.
|
||||
*/
|
||||
suspend fun table(scope: Scope = Scope.All): Result<String, ExecException> {
|
||||
suspend fun table(scope: Scope = Scope.All): Result<String, ExecError> {
|
||||
val options = listOf(null to "--lines", true to "--ascii").makeOptions()
|
||||
return executeAndHandleErrors("table", *scope.options, *options, transformer = ZeroCodeStdoutTransformer)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -127,7 +127,7 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
*
|
||||
* @return true if created, false if already exists
|
||||
*/
|
||||
suspend fun create(envName: String? = null): Result<CreateResult, ExecException> {
|
||||
suspend fun create(envName: String? = null): Result<CreateResult, ExecError> {
|
||||
val arguments = if (envName == null) emptyArray() else arrayOf(envName)
|
||||
return executeAndHandleErrors("create", *arguments) {
|
||||
val actualEnvName = envName ?: DEFAULT_ENV_NAME
|
||||
@@ -145,7 +145,7 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
*
|
||||
* @return path to environment
|
||||
*/
|
||||
suspend fun find(envName: String? = null): Result<PythonHomePath?, ExecException> {
|
||||
suspend fun find(envName: String? = null): Result<PythonHomePath?, ExecError> {
|
||||
val arguments = if (envName == null) emptyArray() else arrayOf(envName)
|
||||
return executeAndHandleErrors("find", *arguments) {
|
||||
when (it.exitCode) {
|
||||
@@ -178,9 +178,9 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
* - [RemoveResult.NotExists] if the environment does not exist.
|
||||
* - [RemoveResult.NotDefinedInConfig] if the environment is not defined in the project configuration.
|
||||
* - [RemoveResult.CantRemoveActiveEnvironment] if the environment cannot be removed because it is currently active.
|
||||
* - An error wrapped in [ExecException] in case of execution failure.
|
||||
* - An error wrapped in [ExecError] in case of execution failure.
|
||||
*/
|
||||
suspend fun remove(envName: String? = null): Result<RemoveResult, ExecException> {
|
||||
suspend fun remove(envName: String? = null): Result<RemoveResult, ExecError> {
|
||||
val arguments = if (envName == null) emptyArray() else arrayOf(envName)
|
||||
return executeAndHandleErrors("remove", *arguments) {
|
||||
val actualEnvName = envName ?: DEFAULT_ENV_NAME
|
||||
@@ -200,9 +200,9 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
* @param envs A vararg parameter specifying the environment names to be displayed. If not provided, information for all environments is shown.
|
||||
* @return A [Result] containing:
|
||||
* - [HatchDetailedEnvironments] if operation is successful.
|
||||
* - An error wrapped in [ExecException] if an execution failure occurs.
|
||||
* - An error wrapped in [ExecError] if an execution failure occurs.
|
||||
*/
|
||||
suspend fun showWithDetails(vararg envs: String): Result<HatchDetailedEnvironments, ExecException> {
|
||||
suspend fun showWithDetails(vararg envs: String): Result<HatchDetailedEnvironments, ExecError> {
|
||||
return executeAndHandleErrors("show", "--json", *envs) { processOutput ->
|
||||
val output = processOutput.takeIf { it.exitCode == 0 }?.stdout
|
||||
?: return@executeAndHandleErrors Result.failure(null)
|
||||
@@ -227,9 +227,9 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
* @param internal Optional parameter indicating whether to include internal environments. Defaults to false.
|
||||
* @return A [Result] containing:
|
||||
* - [HatchDetailedEnvironments] if operation is successful.
|
||||
* - An error wrapped in [ExecException] if an execution failure occurs.
|
||||
* - An error wrapped in [ExecError] if an execution failure occurs.
|
||||
*/
|
||||
suspend fun show(vararg envs: String, internal: Boolean = false): Result<HatchEnvironments, ExecException> {
|
||||
suspend fun show(vararg envs: String, internal: Boolean = false): Result<HatchEnvironments, ExecError> {
|
||||
val options = listOf(internal to "--internal").makeOptions()
|
||||
|
||||
return executeAndMatch("show", "--ascii", *options, *envs, expectedOutput = SHOW_RESPONSE_REGEX) { matchResult ->
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -61,7 +61,7 @@ class HatchProject(runtime: HatchRuntime) : HatchCommand("project", runtime) {
|
||||
/**
|
||||
* Display project metadata
|
||||
*/
|
||||
suspend fun metadata(): Result<Metadata, ExecException> {
|
||||
suspend fun metadata(): Result<Metadata, ExecError> {
|
||||
return executeAndHandleErrors("metadata") { processOutput ->
|
||||
val output = processOutput.takeIf { it.exitCode == 0 }?.stdout
|
||||
?: return@executeAndHandleErrors Result.failure(null)
|
||||
|
||||
@@ -3,10 +3,10 @@ package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.util.io.NioFiles
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.cli.HatchPython.PythonInstallResponse.AbortReason
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ class HatchPython(runtime: HatchRuntime) : HatchCommand("python", runtime) {
|
||||
* @param parent Show the parent directory of the Python binary
|
||||
* @param dir The directory in which distributions reside
|
||||
*/
|
||||
suspend fun find(name: String, parent: Boolean? = null, dir: String? = null): Result<Path?, ExecException> {
|
||||
suspend fun find(name: String, parent: Boolean? = null, dir: String? = null): Result<Path?, ExecError> {
|
||||
val options = listOf(parent to "--parent").makeOptions() + buildDirOption(dir)
|
||||
|
||||
return executeAndHandleErrors("find", *options, name) { output ->
|
||||
@@ -127,7 +127,7 @@ class HatchPython(runtime: HatchRuntime) : HatchCommand("python", runtime) {
|
||||
private: Boolean? = null,
|
||||
update: Boolean? = null,
|
||||
dir: String? = null,
|
||||
): Result<PythonInstallResponse, ExecException> {
|
||||
): Result<PythonInstallResponse, ExecError> {
|
||||
val options = listOf(update to "--update", private to "--private").makeOptions() + buildDirOption(dir)
|
||||
return executeAndHandleErrors("install", *options, *names) { output ->
|
||||
Result.success(parsePythonInstallCommandOutput(output))
|
||||
@@ -142,7 +142,7 @@ class HatchPython(runtime: HatchRuntime) : HatchCommand("python", runtime) {
|
||||
* @param names Distributions to remove, you may select `all` to install all compatible distributions
|
||||
* @param dir The directory in which distributions reside
|
||||
*/
|
||||
suspend fun remove(vararg names: String = ALL_NAMES, dir: String? = null): Result<PythonRemoveResponse, ExecException> {
|
||||
suspend fun remove(vararg names: String = ALL_NAMES, dir: String? = null): Result<PythonRemoveResponse, ExecError> {
|
||||
return executeAndHandleErrors("remove", *buildDirOption(dir), *names) { processOutput ->
|
||||
val output = processOutput.stderr
|
||||
val notInstalledRegex = Regex("""^Distribution is not installed: (.*)$""", RegexOption.MULTILINE)
|
||||
@@ -163,7 +163,7 @@ class HatchPython(runtime: HatchRuntime) : HatchCommand("python", runtime) {
|
||||
* @param dir The directory in which distributions reside
|
||||
* @return Name to Version as a map
|
||||
*/
|
||||
suspend fun show(dir: String? = null): Result<ShowResponse, ExecException> {
|
||||
suspend fun show(dir: String? = null): Result<ShowResponse, ExecError> {
|
||||
val nameToVersionRegex = """\|\s+([^|\s]+)\s+\|\s+([^|\s]+)\s+\|""".toRegex()
|
||||
fun parseNameToVersions(payload: String) = nameToVersionRegex.findAll(payload).associate {
|
||||
val (name, version) = it.destructured
|
||||
@@ -198,7 +198,7 @@ class HatchPython(runtime: HatchRuntime) : HatchCommand("python", runtime) {
|
||||
* @param names Distributions to update, you may select `all` to install all compatible distributions
|
||||
* @param dir The directory in which distributions reside
|
||||
*/
|
||||
suspend fun update(vararg names: String = ALL_NAMES, dir: String? = null): Result<PythonInstallResponse, ExecException> {
|
||||
suspend fun update(vararg names: String = ALL_NAMES, dir: String? = null): Result<PythonInstallResponse, ExecError> {
|
||||
return executeAndHandleErrors("update", *buildDirOption(dir), *names) { output ->
|
||||
Result.success(parsePythonInstallCommandOutput(output))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// 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.hatch.cli
|
||||
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.PyHatchBundle
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.util.Url
|
||||
import com.intellij.util.Urls
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
|
||||
/**
|
||||
* Manage environment dependencies
|
||||
@@ -16,7 +16,7 @@ class HatchSelf(runtime: HatchRuntime) : HatchCommand("self", runtime) {
|
||||
/**
|
||||
* Generate a pre-populated GitHub issue.
|
||||
*/
|
||||
suspend fun report(): Result<Url, ExecException> {
|
||||
suspend fun report(): Result<Url, ExecError> {
|
||||
return executeAndHandleErrors("report", "--no-open") { processOutput ->
|
||||
val output = processOutput.takeIf { it.exitCode == 0 }?.stdout?.trim()
|
||||
?: return@executeAndHandleErrors Result.failure(null)
|
||||
@@ -33,10 +33,10 @@ class HatchSelf(runtime: HatchRuntime) : HatchCommand("self", runtime) {
|
||||
/**
|
||||
* Restore the installation
|
||||
*/
|
||||
fun restore(): Result<String, ExecException> = TODO()
|
||||
fun restore(): Result<String, ExecError> = TODO()
|
||||
|
||||
/**
|
||||
* Install the latest version
|
||||
*/
|
||||
fun update(): Result<String, ExecException> = TODO()
|
||||
fun update(): Result<String, ExecError> = TODO()
|
||||
}
|
||||
@@ -10,11 +10,12 @@ import com.intellij.python.hatch.service.CliBasedHatchService
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.errorProcessing.MessageError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.sdk.basePath
|
||||
import java.nio.file.Path
|
||||
|
||||
sealed class HatchError(message: @NlsSafe String) : PyError.Message(message)
|
||||
sealed class HatchError(message: @NlsSafe String) : MessageError(message)
|
||||
|
||||
class HatchExecutableNotFoundHatchError(path: Path?) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.executable.is.not.found", path.toString())
|
||||
@@ -79,25 +80,25 @@ data class ProjectStructure(
|
||||
interface HatchService {
|
||||
fun getWorkingDirectoryPath(): Path
|
||||
|
||||
suspend fun syncDependencies(envName: String): Result<String, PyError>
|
||||
suspend fun syncDependencies(envName: String): PyResult<String>
|
||||
|
||||
suspend fun isHatchManagedProject(): Result<Boolean, PyError>
|
||||
suspend fun isHatchManagedProject(): PyResult<Boolean>
|
||||
|
||||
suspend fun createNewProject(projectName: String): Result<ProjectStructure, PyError>
|
||||
suspend fun createNewProject(projectName: String): PyResult<ProjectStructure>
|
||||
|
||||
/**
|
||||
* param[basePythonBinaryPath] base python for environment, the one on the PATH should be used if null.
|
||||
* param[envName] environment name to create, 'default' should be used if null.
|
||||
*/
|
||||
suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary? = null, envName: String? = null): Result<PythonVirtualEnvironment.Existing, PyError>
|
||||
suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary? = null, envName: String? = null): PyResult<PythonVirtualEnvironment.Existing>
|
||||
|
||||
suspend fun findVirtualEnvironments(): Result<List<HatchVirtualEnvironment>, PyError>
|
||||
suspend fun findVirtualEnvironments(): PyResult<List<HatchVirtualEnvironment>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Hatch Service for working directory (where hatch.toml / pyproject.toml is usually placed)
|
||||
*/
|
||||
suspend fun Path.getHatchService(hatchExecutablePath: Path? = null): Result<HatchService, PyError> {
|
||||
suspend fun Path.getHatchService(hatchExecutablePath: Path? = null): PyResult<HatchService> {
|
||||
return CliBasedHatchService(hatchExecutablePath = hatchExecutablePath, workingDirectoryPath = this)
|
||||
}
|
||||
|
||||
@@ -105,7 +106,7 @@ suspend fun Path.getHatchService(hatchExecutablePath: Path? = null): Result<Hatc
|
||||
* Hatch Service for Module.
|
||||
* Working directory considered as the module base path.
|
||||
*/
|
||||
suspend fun Module.getHatchService(hatchExecutablePath: Path? = null): Result<HatchService, PyError> {
|
||||
suspend fun Module.getHatchService(hatchExecutablePath: Path? = null): PyResult<HatchService> {
|
||||
val workingDirectoryPath = resolveHatchWorkingDirectory(this.project, this).getOr { return it }
|
||||
return workingDirectoryPath.getHatchService(hatchExecutablePath = hatchExecutablePath)
|
||||
}
|
||||
@@ -115,7 +116,7 @@ suspend fun Module.getHatchService(hatchExecutablePath: Path? = null): Result<Ha
|
||||
*/
|
||||
fun PythonHomePath.getHatchEnvVirtualProjectPath(): Path = this.parent.parent
|
||||
|
||||
fun resolveHatchWorkingDirectory(project: Project, module: Module?): Result<Path, PyError> {
|
||||
fun resolveHatchWorkingDirectory(project: Project, module: Module?): PyResult<Path> {
|
||||
val pathString = module?.basePath ?: project.basePath
|
||||
|
||||
return when (val path = pathString?.let { Path.of(it) }) {
|
||||
|
||||
@@ -12,7 +12,8 @@ import com.intellij.python.hatch.cli.HatchCli
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.errorProcessing.ExecError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.resolvePythonBinary
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.isDirectory
|
||||
@@ -57,15 +58,15 @@ class HatchRuntime(
|
||||
* Pure execution of [hatchBinary] with command line [arguments] and [execOptions] by [execService]
|
||||
* Doesn't make any validation of stdout/stderr content.
|
||||
*/
|
||||
internal suspend fun <T> execute(vararg arguments: String, processOutputTransformer: ProcessOutputTransformer<T>): Result<T, PyError.ExecException> {
|
||||
internal suspend fun <T> execute(vararg arguments: String, processOutputTransformer: ProcessOutputTransformer<T>): Result<T, ExecError> {
|
||||
return execService.execute(hatchBinary, arguments.toList(), execOptions, processOutputTransformer)
|
||||
}
|
||||
|
||||
internal suspend fun <T> executeInteractive(vararg arguments: String, eelProcessInteractiveHandler: EelProcessInteractiveHandler<T>): Result<T, PyError.ExecException> {
|
||||
internal suspend fun <T> executeInteractive(vararg arguments: String, eelProcessInteractiveHandler: EelProcessInteractiveHandler<T>): Result<T, ExecError> {
|
||||
return execService.executeInteractive(hatchBinary, arguments.toList(), execOptions, eelProcessInteractiveHandler)
|
||||
}
|
||||
|
||||
internal suspend fun resolvePythonVirtualEnvironment(pythonHomePath: PythonHomePath): Result<PythonVirtualEnvironment, PyError> {
|
||||
internal suspend fun resolvePythonVirtualEnvironment(pythonHomePath: PythonHomePath): PyResult<PythonVirtualEnvironment> {
|
||||
val pythonVersion = pythonHomePath.takeIf { it.isDirectory() }?.resolvePythonBinary()?.let { pythonBinaryPath ->
|
||||
execService.execGetStdout(Binary(pythonBinaryPath), listOf("--version")).getOr { return it }.trim()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.createHatchRuntime
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
@@ -30,7 +30,7 @@ internal class CliBasedHatchService private constructor(
|
||||
private val hatchRuntime: HatchRuntime,
|
||||
) : HatchService {
|
||||
companion object {
|
||||
suspend operator fun invoke(workingDirectoryPath: Path, hatchExecutablePath: Path?): Result<CliBasedHatchService, PyError> {
|
||||
suspend operator fun invoke(workingDirectoryPath: Path, hatchExecutablePath: Path?): PyResult<CliBasedHatchService> {
|
||||
val hatchRuntime = createHatchRuntime(
|
||||
hatchExecutablePath = hatchExecutablePath,
|
||||
workingDirectoryPath = workingDirectoryPath,
|
||||
@@ -51,13 +51,13 @@ internal class CliBasedHatchService private constructor(
|
||||
|
||||
override fun getWorkingDirectoryPath(): Path = workingDirectoryPath
|
||||
|
||||
override suspend fun syncDependencies(envName: String): Result<String, PyError> {
|
||||
override suspend fun syncDependencies(envName: String): PyResult<String> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
hatchRuntime.hatchCli().run(envName, "python", "--version")
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isHatchManagedProject(): Result<Boolean, PyError> {
|
||||
override suspend fun isHatchManagedProject(): PyResult<Boolean> {
|
||||
val isHatchManaged = withContext(Dispatchers.IO) {
|
||||
when {
|
||||
workingDirectoryPath.resolve("hatch.toml").exists() -> true
|
||||
@@ -72,7 +72,7 @@ internal class CliBasedHatchService private constructor(
|
||||
}
|
||||
|
||||
|
||||
override suspend fun findVirtualEnvironments(): Result<List<HatchVirtualEnvironment>, PyError> {
|
||||
override suspend fun findVirtualEnvironments(): PyResult<List<HatchVirtualEnvironment>> {
|
||||
val hatchEnv = hatchRuntime.hatchCli().env()
|
||||
val environments: HatchEnvironments = hatchEnv.show().getOr { return it }
|
||||
val virtualEnvironments = environments.getAvailableVirtualHatchEnvironments()
|
||||
@@ -90,7 +90,7 @@ internal class CliBasedHatchService private constructor(
|
||||
}
|
||||
|
||||
|
||||
override suspend fun createNewProject(projectName: String): Result<ProjectStructure, PyError> {
|
||||
override suspend fun createNewProject(projectName: String): PyResult<ProjectStructure> {
|
||||
val eelApi = workingDirectoryPath.getEelDescriptor().upgrade()
|
||||
val tempDir = eelApi.fs.createTemporaryDirectory(EelFileSystemApi.CreateTemporaryEntryOptions.Builder().build()).getOr { failure ->
|
||||
return Result.failure(FileSystemOperationHatchError(failure.error))
|
||||
@@ -108,7 +108,7 @@ internal class CliBasedHatchService private constructor(
|
||||
))
|
||||
}
|
||||
|
||||
override suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary?, envName: String?): Result<PythonVirtualEnvironment.Existing, PyError> {
|
||||
override suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary?, envName: String?): PyResult<PythonVirtualEnvironment.Existing> {
|
||||
val pythonBasedRuntime = basePythonBinaryPath?.let { path ->
|
||||
hatchRuntime.withBasePythonBinaryPath(path).getOr { return it }
|
||||
} ?: hatchRuntime
|
||||
|
||||
Reference in New Issue
Block a user