Path:
strictdoc/cli/cli_arg_parser.py
Lines:
118
Non-empty lines:
100
Non-empty lines covered with requirements:
100 / 100 (100.0%)
Functions:
9
Functions covered by requirements:
9 / 9 (100.0%)
1
import argparse
2
import sys
3
from typing import Any, Dict, NoReturn
4
5
from strictdoc import __version__
6
from strictdoc.helpers.cast import assert_cast
7
from strictdoc.helpers.parallelizer import Parallelizer
8
9
10
def formatter(prog: str) -> argparse.RawTextHelpFormatter:
11
return argparse.RawTextHelpFormatter(
12
prog, indent_increment=2, max_help_position=4, width=80
13
)14
15
16
class SDocArgumentParser(argparse.ArgumentParser):
17
def error(self, message: str) -> NoReturn:
18
self.print_usage(sys.stderr)
19
print(f"{self.prog}: error: {message}", file=sys.stderr) # noqa: T201
20
print("") # noqa: T201
21
print("Further help:") # noqa: T201
22
print( # noqa: T201
23
"'strictdoc -h/--help' provides a general overview of available commands."24
)25
print( # noqa: T201
26
"'strictdoc <command> -h/--help' provides command-specific help."27
)28
sys.exit(2)
29
30
31
class SDocArgsParser:
32
@classmethod33
def create_sdoc_args_parser(
34
cls, registry: Dict[str, Any]
35
) -> "SDocArgsParser":
36
parser = cls.build_argparse(registry)
37
args = parser.parse_args()
38
return cls(args, registry)
39
40
def __init__(self, args: argparse.Namespace, registry: Dict[str, Any]):
41
self.args: argparse.Namespace = args
42
self.registry: Dict[str, Any] = registry
43
44
def is_debug_mode(self) -> bool:
45
return assert_cast(self.args.debug, bool)
46
47
def run(self, parallelizer: Parallelizer) -> bool:
48
if self.args.command not in self.registry:
49
return False
50
51
cmd = self.registry[self.args.command]
52
if isinstance(cmd, dict):
53
assert self.args.subcommand in cmd
54
command_instance = cmd[self.args.subcommand](self.args)
55
else:
56
command_instance = cmd(self.args)
57
command_instance.run(parallelizer)
58
59
return True
60
61
@classmethod62
def build_argparse(cls, registry: Dict[str, Any]) -> SDocArgumentParser:
63
# https://stackoverflow.com/a/19476216/59805764
main_parser = SDocArgumentParser(
65
prog="strictdoc",
66
add_help=True,
67
epilog=(
68
"""
69
Further help: https://strictdoc.readthedocs.io/en/stable/70
"""71
),72
)73
74
# The -v/--version has a special behavior that it still works when all75
# commands are required == True.76
# https://stackoverflow.com/a/12123598/59805777
main_parser.add_argument(
78
"-v", "--version", action="version", version=__version__
79
)80
81
main_parser.add_argument(
82
"--debug",
83
action="store_true",
84
default=False,
85
help="Enable more verbose printing of errors when they are encountered.",
86
)87
88
command_subparsers = main_parser.add_subparsers(
89
title="command", dest="command"
90
)91
command_subparsers.required = True
92
93
# Dynamically add subcommands94
for name, cmd in registry.items():
95
if isinstance(cmd, dict): # command family
96
family_parser = command_subparsers.add_parser(name)
97
family_subparsers = family_parser.add_subparsers(
98
dest="subcommand"
99
)100
family_subparsers.required = True
101
for subname, subcmd in cmd.items():
102
sub_parser = family_subparsers.add_parser(
103
subname,
104
help=subcmd.HELP,
105
description=subcmd.DETAILED_HELP,
106
formatter_class=formatter,
107
)108
subcmd.add_arguments(sub_parser)
109
else:
110
cmd_parser = command_subparsers.add_parser(
111
name,
112
help=cmd.HELP,
113
description=cmd.DETAILED_HELP,
114
formatter_class=formatter,
115
)116
cmd.add_arguments(cmd_parser)
117
118
return main_parser