Source code for app.util.config.args.parser

# SPDX-License-Identifier: GPLv3-or-later
# Copyright © 2025 pygaindalf Rui Pinheiro

"""
Argument parsing and CLI option definitions for pygaindalf
Defines global options, command actions, and wraps argparse for use throughout the application.
"""

import argparse
import os
import sys

from typing import Sequence, override
from abc import ABCMeta, abstractmethod

from ...helpers.script_info import get_script_name, is_unit_test, get_exe_name

###################
# Argument parser

ENV_PREFIX = get_script_name().upper()

[docs] class ArgParserBase(argparse.ArgumentParser, metaclass=ABCMeta):
[docs] def __init__(self, *args, **kwargs): kwargs['prog'] = kwargs.get('prog', get_exe_name()) kwargs['description'] = kwargs.get('description', "pygaindalf CLI options") kwargs['formatter_class'] = argparse.ArgumentDefaultsHelpFormatter super().__init__(*args, **kwargs) self.initialize() self.parse()
[docs] @override def add_argument(self, name : str, *args, default=None, **kwargs) -> argparse.Action: """ Add a command-line argument to the global parser. Args: name (str): The destination variable name. *args: Argument flags (e.g., '-v', '--verbosity'). default: Default value if not set elsewhere. **kwargs: Additional argparse options. """ env_name = name.upper().replace('.', '_') return super().add_argument(*args, dest=name, default=os.getenv(f"{ENV_PREFIX}_{env_name}", default), **kwargs )
[docs] def add(self, *args, **kwargs) -> argparse.Action: return self.add_argument(*args, **kwargs)
[docs] @abstractmethod def initialize(self) -> None: raise NotImplementedError("Subclasses must implement the 'initialize' method.")
[docs] def get_argv(self) -> Sequence[str]: if is_unit_test(): # In unit tests, we default to reading the config from stdin return ('-',) return sys.argv[1:]
[docs] @override def parse_args(self, *args, **kwargs) -> argparse.Namespace: """ Get the parsed command-line arguments. Returns: argparse.Namespace: The parsed arguments. """ self.namespace = super().parse_args(self.get_argv(), *args, **kwargs) return self.namespace
[docs] def parse(self, *args, **kwargs) -> argparse.Namespace: return self.parse_args(*args, **kwargs)