"""Output-format selection and fatal error rendering."""
from __future__ import annotations
from enum import StrEnum
from typing import TYPE_CHECKING, NoReturn
import typer
from peta.cli.output.console import inline
from peta.cli.output.json import format_error
from peta.core.cache import redacted_text
if TYPE_CHECKING:
from peta.core.output import CommandName, MessageCode
__all__ = ["OutputFormat", "fail", "resolve_or_fail", "resolve_output_format"]
[docs]
def resolve_or_fail(
command: CommandName,
arguments: dict[str, object],
output_format: OutputFormat | None,
*,
use_json: bool,
) -> OutputFormat:
"""Resolve output selection, using a JSON envelope for JSON conflicts.
Returns:
The selected output format.
"""
try:
return resolve_output_format(output_format, use_json=use_json)
except typer.BadParameter as exc:
selected = (
OutputFormat.JSON if use_json else (output_format or OutputFormat.RICH)
)
fail(
command,
arguments=arguments,
code="invalid_arguments",
message=str(exc),
output_format=selected,
exit_code=2,
)
[docs]
def fail(
command: CommandName,
*,
arguments: dict[str, object],
code: MessageCode,
message: str,
output_format: OutputFormat,
exit_code: int,
source: str | None = None,
) -> NoReturn:
"""Render a fatal error consistently and exit.
Raises:
Exit: Always, using ``exit_code``.
"""
rendered = (
format_error(
command, arguments=arguments, code=code, message=message, source=source
)
if output_format == OutputFormat.JSON
# The JSON branch redacts through ``OutputMessage`` and escapes
# control characters itself. This one goes straight to a terminal, and
# the message can quote a URL peta requested or text an index chose —
# a malformed key ends up in a validation error's path — so it is held
# to one line as well as stripped of controls.
else inline(redacted_text(message))
)
typer.echo(rendered, err=True)
raise typer.Exit(code=exit_code)