Coverage for src/pydal2sql/typer_support.py: 100%
33 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-04-22 14:51 +0200
« prev ^ index » next coverage.py v7.11.0, created at 2026-04-22 14:51 +0200
1"""
2Cli-specific support.
3"""
5import contextlib
6import functools
7import os
8import sys
9from pathlib import Path
10from typing import Any, Never
12import dotenv
13import rich
14import typer
15from pydal2sql_core.state import (
16 DEFAULT_VERBOSITY,
17 AbstractConfig,
18 ApplicationState,
19 Config,
20 DB_Types,
21 DynamicEnum,
22 MaybeConfig,
23 ReprEnumMeta,
24 Verbosity,
25 Verbosity_Comparable,
26 create_enum_from_literal,
27 get_pydal2sql_config,
28 state,
29)
30from su6 import find_project_root
31from su6.core import (
32 EXIT_CODE_ERROR,
33 EXIT_CODE_SUCCESS,
34 T_Command,
35 T_Inner_Wrapper,
36 T_Outer_Wrapper,
37)
39__all__ = [
40 "DEFAULT_VERBOSITY",
41 "IS_DEBUG",
42 "AbstractConfig",
43 "ApplicationState",
44 "Config",
45 "DB_Types",
46 "DynamicEnum",
47 "MaybeConfig",
48 "ReprEnumMeta",
49 "Verbosity",
50 "Verbosity_Comparable",
51 "create_enum_from_literal",
52 "get_pydal2sql_config",
53 "is_debug",
54 "state",
55 "with_exit_code",
56]
59def with_exit_code(hide_tb: bool = True) -> T_Outer_Wrapper:
60 """
61 Convert the return value of an app.command (bool or int) to an typer Exit with return code, \
62 Unless the return value is Falsey, in which case the default exit happens (with exit code 0 indicating success).
64 Usage:
65 > @app.command()
66 > @with_exit_code()
67 def some_command(): ...
69 When calling a command from a different command, _suppress=True can be added to not raise an Exit exception.
71 See Also:
72 github.com:trialandsuccess/su6-checker
73 """
75 def outer_wrapper(func: T_Command) -> T_Inner_Wrapper:
76 @functools.wraps(func)
77 def inner_wrapper(*args: Any, **kwargs: Any) -> Never:
78 try:
79 result = func(*args, **kwargs)
80 except Exception as e:
81 result = EXIT_CODE_ERROR
82 if hide_tb:
83 rich.print(f"[red]{e}[/red]", file=sys.stderr)
84 else: # pragma: no cover
85 raise e
86 finally:
87 sys.stdout.flush()
88 sys.stderr.flush()
90 if result is True:
91 # assume no issue then
92 result = EXIT_CODE_SUCCESS
93 elif result is False:
94 result = EXIT_CODE_ERROR
96 raise typer.Exit(code=int(result or 0))
98 return inner_wrapper
100 return outer_wrapper
103def _is_debug() -> bool: # pragma: no cover
104 folder, _ = find_project_root((os.getcwd(),))
105 if not folder:
106 folder = Path(os.getcwd())
107 dotenv.load_dotenv(folder / ".env")
109 return os.getenv("IS_DEBUG") == "1"
112def is_debug() -> bool: # pragma: no cover
113 """
114 Returns whether IS_DEBUG = 1 in the .env.
115 """
116 with contextlib.suppress(Exception):
117 return _is_debug()
118 return False
121IS_DEBUG = is_debug()