argparse2rst.py 1.51 KB
Newer Older
sunzhq2's avatar
sunzhq2 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python3
import importlib.machinery as imm
import logging
import pathlib
import re

import configargparse


class ModuleInfo:
    def __init__(self, path):
        self.path = pathlib.Path(path)
        name = str(self.path.parent / self.path.stem)
        name = name.replace("/", ".")
        self.name = re.sub(r"^[\.]+", "", name)
        self.module = imm.SourceFileLoader(self.name, path).load_module()
        if not hasattr(self.module, "get_parser"):
            raise ValueError(f"{path} does not have get_parser()")


def get_parser():
    parser = configargparse.ArgumentParser(
        description="generate RST from argparse options",
        config_file_parser_class=configargparse.YAMLConfigFileParser,
        formatter_class=configargparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        "src",
        type=str,
        nargs="+",
        help="source python files that contain get_parser() func",
    )
    return parser


# parser
args = get_parser().parse_args()


modinfo = []

for p in args.src:
    if "__init__.py" in p:
        continue
    modinfo.append(ModuleInfo(p))


# print refs
for m in modinfo:
    logging.info(f"processing: {m.path.name}")
    d = m.module.get_parser().description
    assert d is not None
    print(f"- :ref:`{m.path.name}`: {d}")

print()

# print argparse
for m in modinfo:
    cmd = m.path.name
    sep = "~" * len(cmd)
    print(
        f"""

.. _{cmd}:

{cmd}
{sep}

.. argparse::
   :module: {m.name}
   :func: get_parser
   :prog: {cmd}

"""
    )