Source code for src.hformatter

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Utility class to format help text.

:module: hformatter
:author: Le Bars, Yoann

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License  as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. See file `LICENSE` or go to:

https://www.gnu.org/licenses/gpl-3.0.html
"""


# Defines the public names of this module.
__all__ = ['InvalidCommandLine', 'create_parser']


from typing import Final, Iterable
import argparse
from sys import stderr
from functools import partial


# Title for usage section.
USAGE_STRING: str = 'Usage: '
# Title for default value description.
DEFAULT_STRING: str = 'default'


[docs] class InvalidCommandLine(Exception): """ Exception raised when the command line is invalid. :param str message: Error message. """ message: str def __init__(self, message: str, *args: object) -> None: """ Class constructor. :param str message: Error message. :param object args: Optional arguments list. """ self.message: Final[str] = message super().__init__(*args)
class HelpFormatter(argparse.ArgumentDefaultsHelpFormatter): """ Class to format help output. :param str __usage_string: Title for usage section. :param str __default_string: Title for default value description. """ __usage_string: str __default_string: str def __init__(self, prog: str, indent_increment: int = 2, max_help_position: int = 24, # pylint: disable=too-many-arguments, too-many-positional-arguments width: int | None = None, usage_str: str | None = None, default_str: str | None = None) -> None: """ Class constructor. :param str prog: Program name. :param int indent_increment: Number of blank space when incrementing the text. :param int max_help_position: Maximum text indent. :param int width: Line width in help message. :param str usage_str: Title for usage section. :param str default_str: Title for default value description. """ self.__usage_string = usage_str if usage_str is not None else USAGE_STRING self.__default_string = default_str if default_str is not None else DEFAULT_STRING super().__init__(prog, indent_increment, max_help_position, width) def _get_help_string(self, action: argparse.Action) -> str | None: """ Create the help message for a given action. :param argparse.Action action: Action descriptor. """ help_string: str | None = action.help if '%(default)' not in action.help: if action.default is not argparse.SUPPRESS: defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE] if action.option_strings or action.nargs in defaulting_nargs: help_string += f' ({self.__default_string}: %(default)s)' return help_string def add_usage(self, usage: str, actions: Iterable[argparse.Action], groups: Iterable[argparse._ArgumentGroup], prefix: str | None = None) -> None: """ Reformat usage message. :param str usage: Program command line description. :param Iterable[argparse.Action] actions: Action identifier. :param Iterable[argparse._ArgumentGroup] groups: Groups identifier. :param str prefix: Prefix to usage explanation. :returns: Object describing usage string. :rtype: None """ if prefix is None: prefix = self.__usage_string return super().add_usage(usage, actions, groups, prefix) class PersonalizedArgumentParser(argparse.ArgumentParser): """ Argument parser with translated error messages. """ def error(self, message: str) -> None: """ Prints a usage message incorporating the message to stderr and raises an exception. :param str message: Error message. :raises InvalidCommandLine: If the command line is invalid. """ self.print_usage(stderr) raise InvalidCommandLine(message)
[docs] def create_parser(program_description: str, positional_name: str, optional_name: str, # pylint: disable=too-many-arguments, too-many-positional-arguments program_version: str, version_message: str, help_message: str, usage_message: str = USAGE_STRING, default_message: str = DEFAULT_STRING) -> PersonalizedArgumentParser: """ Generates an argument parser. :param str program_description: String describing the aims of the program. :param str positional_name: String for positional arguments title. :param str optional_name: String for optional arguments title. :param str program_version: String describing program version. :param str version_message: String describing the version program option. :param str help_message: String describing the help program option. :param str usage_message: Title for usage section. Defaults to “Usage: ”. :param str default_message: Title for default value description. Defaults to “default”. :returns: An argument parser. :rtype: PersonalizedArgumentParser """ # Command line parser. formatter = partial(HelpFormatter, usage_str=usage_message, default_str=default_message) parser = PersonalizedArgumentParser(add_help=False, formatter_class=formatter, description=program_description) parser._positionals.title = positional_name # pylint: disable=protected-access parser._optionals.title = optional_name # pylint: disable=protected-access parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + program_version, help=version_message) parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help=help_message) return parser