Source code for gamesheet_sdk.common.cli.helpers
# Copyright (c) 2026 bdperkin
# SPDX-License-Identifier: MIT
"""CLI helper functions shared across command modules."""
from __future__ import annotations
from typing import TYPE_CHECKING, TypeVar
import rich_click as click
from click import get_current_context
from click.exceptions import Exit
from click.shell_completion import get_completion_class # type: ignore[unresolved-import]
from gamesheet_sdk.common.exceptions import AuthenticationError, GameSheetError
if TYPE_CHECKING:
from collections.abc import Callable
from gamesheet_sdk.common.auth.session import BaseAuthenticatedSession
_R = TypeVar("_R")
[docs]
def run_action_or_exit(
session: BaseAuthenticatedSession,
action: Callable[..., _R],
*args: object,
**kwargs: object,
) -> _R:
"""Run an action function with error handling.
Wraps the action call in the session's context manager and catches :exc:`AuthenticationError`
and :exc:`GameSheetError`. On either exception, prints a user-friendly error message to
stderr and exits with code 1. The session context manager ensures proper cleanup (e.g.,
closing connections) regardless of success or failure.
Args:
session (BaseAuthenticatedSession): The authenticated session to use as a context manager.
action (Callable[..., _R]): A callable that takes ``session`` and ``*args`` and returns
a result. Typically a domain action function (e.g., ``list_associations``).
*args (object): Positional arguments forwarded to ``action`` after ``session``.
**kwargs (object): Keyword arguments forwarded to ``action``.
Returns:
_R: The result of ``action(session, *args, **kwargs)`` on success.
Raises:
Exit: If ``action`` raises :exc:`AuthenticationError` or :exc:`GameSheetError`. Exit code
is 1 in both cases.
"""
try:
with session:
return action(session, *args, **kwargs)
except AuthenticationError as exc:
click.secho(f"Authentication required: {exc}", fg="red", err=True)
raise Exit(1) from exc
except GameSheetError as exc:
click.secho(f"GameSheet error: {exc}", fg="red", err=True)
raise Exit(1) from exc
[docs]
def emit_shell_completion(
shell: str,
prog_name: str,
complete_var: str,
) -> None:
"""Emit shell completion script for the specified shell.
Args:
shell (str): Target shell (bash, zsh, or fish).
prog_name (str): The CLI program name.
complete_var (str): Environment variable name for completion.
Raises:
Exit: If the specified shell is unsupported.
"""
cls = get_completion_class(shell)
if cls is None: # pragma: no cover
click.secho(f"Unsupported shell: {shell}", fg="red", err=True)
raise Exit(1)
ctx = get_current_context()
if ctx.parent:
comp = cls(
ctx.parent.command,
ctx_args={},
prog_name=prog_name,
complete_var=complete_var,
)
click.echo(comp.source())