From f02f92b80b09d74f7732c4cf028693cb09192924 Mon Sep 17 00:00:00 2001 From: Benexl Date: Sun, 13 Jul 2025 12:29:06 +0300 Subject: [PATCH] feat: custom exception handling --- fastanime/cli/cli.py | 68 +++++++++++++++++++++++++++---- fastanime/cli/utils/exceptions.py | 16 ++++++++ fastanime/cli/utils/logging.py | 4 +- fastanime/core/constants.py | 1 + 4 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 fastanime/cli/utils/exceptions.py diff --git a/fastanime/cli/cli.py b/fastanime/cli/cli.py index f808579..6fcd53b 100644 --- a/fastanime/cli/cli.py +++ b/fastanime/cli/cli.py @@ -1,42 +1,92 @@ +from typing import TYPE_CHECKING + import click from click.core import ParameterSource from .. import __version__ from ..core.config import AppConfig -from ..core.constants import APP_NAME, USER_CONFIG_PATH +from ..core.constants import PROJECT_NAME, USER_CONFIG_PATH from .config import ConfigLoader from .options import options_from_model +from .utils.exceptions import setup_exceptions_handler from .utils.lazyloader import LazyGroup from .utils.logging import setup_logging +if TYPE_CHECKING: + from typing import TypedDict + + from typing_extensions import Unpack + + class Options(TypedDict): + no_config: bool | None + trace: bool | None + log_to_file: bool | None + dev: bool | None + log: bool | None + rich_traceback: bool | None + + commands = { "config": ".config", "search": ".search", } -@click.version_option(__version__, "--version") -@click.option("--no-config", is_flag=True, help="Don't load the user config file.") @click.group( cls=LazyGroup, root="fastanime.cli.commands", lazy_subcommands=commands, - context_settings=dict(auto_envvar_prefix=APP_NAME), + context_settings=dict(auto_envvar_prefix=PROJECT_NAME), +) +@click.version_option(__version__, "--version") +@click.option( + "--no-config", + is_flag=True, + help="Don't load the user config file.", + envvar=f"{PROJECT_NAME}_NO_CONFIG", +) +@click.option( + "--trace", + is_flag=True, + help="Controls Whether to display tracebacks or not", + envvar=f"{PROJECT_NAME}_TRACE", +) +@click.option( + "--dev", + is_flag=True, + help="Controls Whether the app is in dev mode", + envvar=f"{PROJECT_NAME}_DEV", +) +@click.option( + "--log", is_flag=True, help="Controls Whether to log", envvar=f"{PROJECT_NAME}_LOG" +) +@click.option( + "--log-to-file", + is_flag=True, + help="Controls Whether to log to a file", + envvar=f"{PROJECT_NAME}_LOG_TO_FILE", +) +@click.option( + "--rich-traceback", + is_flag=True, + help="Controls Whether to display a rich traceback", + envvar=f"{PROJECT_NAME}_LOG_TO_FILE", ) @options_from_model(AppConfig) @click.pass_context -def cli(ctx: click.Context, no_config: bool, **kwargs): +def cli(ctx: click.Context, **options: "Unpack[Options]"): """ The main entry point for the FastAnime CLI. """ setup_logging( - kwargs.get("log", False), - kwargs.get("log_file", False), - kwargs.get("rich_traceback", False), + options["log"], + options["log_to_file"], + options["rich_traceback"], ) + setup_exceptions_handler(options["trace"], options["dev"]) loader = ConfigLoader(config_path=USER_CONFIG_PATH) - config = AppConfig.model_validate({}) if no_config else loader.load() + config = AppConfig.model_validate({}) if options["no_config"] else loader.load() # update app config with command line parameters for param_name, param_value in ctx.params.items(): diff --git a/fastanime/cli/utils/exceptions.py b/fastanime/cli/utils/exceptions.py new file mode 100644 index 0000000..6b6c247 --- /dev/null +++ b/fastanime/cli/utils/exceptions.py @@ -0,0 +1,16 @@ +import sys + + +def custom_exception_hook(exc_type, exc_value, exc_traceback): + print(f"{exc_type.__name__}: {exc_value}") + + +default_exception_hook = sys.excepthook +# sys.tracebacklimit = 0 + + +def setup_exceptions_handler(trace: bool | None, dev: bool | None): + if trace or dev: + sys.excepthook = default_exception_hook + else: + sys.excepthook = custom_exception_hook diff --git a/fastanime/cli/utils/logging.py b/fastanime/cli/utils/logging.py index c4717ef..8499139 100644 --- a/fastanime/cli/utils/logging.py +++ b/fastanime/cli/utils/logging.py @@ -5,7 +5,9 @@ from rich.traceback import install as rich_install from ...core.constants import LOG_FILE_PATH -def setup_logging(log: bool, log_file: bool, rich_traceback: bool) -> None: +def setup_logging( + log: bool | None, log_file: bool | None, rich_traceback: bool | None +) -> None: """Configures the application's logging based on CLI flags.""" if rich_traceback: rich_install(show_locals=True) diff --git a/fastanime/core/constants.py b/fastanime/core/constants.py index 4335eeb..8122c1d 100644 --- a/fastanime/core/constants.py +++ b/fastanime/core/constants.py @@ -5,6 +5,7 @@ from pathlib import Path PLATFORM = sys.platform APP_NAME = os.environ.get("FASTANIME_APP_NAME", "fastanime") +PROJECT_NAME = "FASTANIME" try: APP_DIR = Path(str(resources.files("fastanime")))