Coverage for src/lilbee/cli/commands/_shared.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-11-06 08:17 +0000

1"""Constants and small rendering helpers shared across the CLI command submodules.""" 

2 

3from __future__ import annotations 

4 

5import json 

6from collections.abc import Callable 

7from typing import Any, NoReturn, TypeVar 

8 

9import typer 

10from pydantic import BaseModel 

11from pydantic_core import to_jsonable_python 

12from rich.text import Text 

13 

14from lilbee.cli import theme 

15from lilbee.cli.app import console 

16from lilbee.cli.helpers import json_output, print_prefixed 

17from lilbee.core.config import cfg 

18 

19CHUNK_PREVIEW_LEN = 80 # characters shown in human-readable search output 

20MAX_FAILURES_SHOWN = 5 # file names shown before "and N more" 

21 

22REBUILD_HINT = "Run lilbee rebuild so the index uses the new values." 

23 

24T = TypeVar("T") 

25 

26 

27def shown_value(value: Any) -> str: 

28 """A setting value the way a profile or config file writes it: "auto", true, 512.""" 

29 return json.dumps(to_jsonable_python(value)) 

30 

31 

32def emit(model: BaseModel, render: Callable[[], None]) -> None: 

33 """Print *model* as JSON in --json mode, else run *render*.""" 

34 if cfg.json_mode: 

35 json_output(model.model_dump(mode="json")) 

36 else: 

37 render() 

38 

39 

40def fail(message: str) -> NoReturn: 

41 """Print *message* as the command's error, as JSON or text, and exit 1.""" 

42 if cfg.json_mode: 

43 json_output({"error": message}) 

44 else: 

45 print_prefixed(console, "Error: ", message, style=theme.ERROR) 

46 raise typer.Exit(1) 

47 

48 

49def line(text: str, style: str | None = None) -> None: 

50 """Print one line of plain text, soft-wrapped.""" 

51 console.print(Text(text, style=style or ""), soft_wrap=True) 

52 

53 

54def run_or_fail(operation: Callable[[], T], os_error_message: Callable[[OSError], str]) -> T: 

55 """Run *operation*; a refusal prints its reason, as JSON or text, and exits 1.""" 

56 try: 

57 return operation() 

58 except (ValueError, KeyError) as exc: 

59 fail(str(exc)) 

60 except OSError as exc: 

61 fail(os_error_message(exc))