Skip to content

Commit ae70d05

Browse files
Andreas Kunzewjakob
authored andcommitted
extended console script entry point and use argparse module instead of manual parsing
1 parent aea9e64 commit ae70d05

File tree

1 file changed

+112
-41
lines changed

1 file changed

+112
-41
lines changed

pybind11_mkdoc/__init__.py

Lines changed: 112 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,63 +5,134 @@
55
"""
66

77

8+
import argparse
9+
import os
10+
import re
11+
import shlex
812
import sys
913

1014
from .mkdoc_lib import mkdoc
1115

1216

1317
__version__ = "2.6.1.dev1"
1418

15-
def main():
16-
mkdoc_out = None
17-
mkdoc_help = False
18-
mkdoc_args = []
19-
docstring_width = None
20-
21-
i = 1
22-
while i < len(sys.argv):
23-
arg = sys.argv[i]
24-
25-
if arg == '-h':
26-
mkdoc_help = True
27-
elif arg == '-o':
28-
mkdoc_out = sys.argv[i + 1]
29-
i += 1 # Skip next
30-
elif arg.startswith('-o'):
31-
mkdoc_out = arg[2:]
32-
elif arg == '-w':
33-
docstring_width = int(sys.argv[i + 1])
34-
i += 1 # Skip next
35-
elif arg.startswith('-w'):
36-
docstring_width = int(arg[2:])
37-
elif arg == '-I':
38-
# Concatenate include directive and path
39-
mkdoc_args.append(arg + sys.argv[i + 1])
40-
i += 1 # Skip next
19+
20+
def _append_include_dir(args: list, include_dir: str, verbose: bool = True):
21+
"""
22+
Add an include directory to an argument list (if it exists).
23+
24+
Parameters
25+
----------
26+
27+
args: list
28+
The list to append the include directory to.
29+
30+
include_dir: str
31+
The include directory to append.
32+
33+
verbose: bool
34+
Whether to print a warning for non-existing directories.
35+
"""
36+
37+
if os.path.isdir(include_dir):
38+
args.append(f"-I{shlex.quote(include_dir)}")
39+
elif verbose:
40+
print(f"Include directoy '{shlex.quote(include_dir)}' does not exist!")
41+
42+
43+
def _append_definition(args: list, definition: str, verbose: bool = True):
44+
"""
45+
Add a compiler definition to an argument list.
46+
47+
The definition is expected to be given in the format '<macro>=<value>',
48+
which will define <macro> to <value> (or 1 if <value> is omitted).
49+
50+
Parameters
51+
----------
52+
53+
args: list
54+
The list to append the definition to.
55+
56+
definition: str
57+
The definition to append.
58+
59+
verbose: bool
60+
Whether to print a warning for invalid definition strings.
61+
"""
62+
63+
try:
64+
macro, value = definition.strip().split('=')
65+
macro = shlex.quote(macro.strip())
66+
value = shlex.quote(value.strip()) if value else '1'
67+
68+
args.append(f"-D{macro}={value}")
69+
except ValueError as exc:
70+
# most likely means there was no '=' given
71+
# check if argument is valid identifier
72+
if re.search(r'^[A-Za-z_][A-Za-z0-9_]*', definition):
73+
args.append(f"-D{definition}")
4174
else:
42-
mkdoc_args.append(arg)
43-
i += 1
75+
print(f"Failed to parse definition: {shlex.quote(definition)}")
76+
except:
77+
print(f"Failed to parse definition: {shlex.quote(definition)}")
4478

45-
if len(mkdoc_args) == 0 or mkdoc_help:
46-
print("""Syntax: python -m pybind11_mkdoc [options] .. list of headers files ..
4779

48-
This tool processes a sequence of C/C++ headers and extracts comments for use
49-
in pybind11 binding code.
5080

51-
Options:
81+
def main():
82+
"""
83+
Entry point for the `pybind11_mkdoc` console script.
84+
85+
Parses the commandline arguments given to the console script and passes them on to `mkdoc`.
86+
"""
87+
88+
parser = argparse.ArgumentParser(
89+
prog='pybind11_mkdoc',
90+
description="Processes a sequence of C/C++ headers and extracts comments for use in pybind11 binding code.",
91+
epilog="(Other compiler flags that Clang understands can also be supplied)",
92+
allow_abbrev=False)
5293

53-
-h Display this help text
94+
parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}")
5495

55-
-o <filename> Write to the specified filename (default: use stdout)
96+
parser.add_argument("-o", "--output", action="store", type=str, dest="output", metavar="<file>",
97+
help="Write to the specified file (default: use stdout).")
5698

57-
-w <width> Specify docstring width before wrapping
99+
parser.add_argument("-w", "--width", action="store", type=int, dest="width", metavar="<width>",
100+
help="Specify docstring width before wrapping.")
58101

59-
-I <path> Specify an include directory
102+
parser.add_argument("-I", action="append", type=str, dest="include_dirs", metavar="<dir>",
103+
help="Specify an directory to add to the list of include search paths.")
104+
105+
parser.add_argument("-D", action="append", type=str, metavar="<macro>=<value>", dest="definitions",
106+
help="Specify a compiler definition, i.e. define <macro> to <value> (or 1 if <value> omitted).")
107+
108+
parser.add_argument("header", type=str, nargs='+', help="A header file to process.")
109+
110+
[parsed_args, unparsed_args] = parser.parse_known_args()
111+
112+
mkdoc_args = []
113+
mkdoc_out = parsed_args.output
114+
docstring_width = parsed_args.width
115+
116+
if parsed_args.include_dirs is not None:
117+
for include_dir in parsed_args.include_dirs:
118+
_append_include_dir(mkdoc_args, include_dir)
119+
120+
if parsed_args.definitions is not None:
121+
for definition in parsed_args.definitions:
122+
_append_definition(mkdoc_args, definition)
123+
124+
for arg in unparsed_args:
125+
if arg.startswith("-I"):
126+
_append_include_dir(mkdoc_args, arg[2:])
127+
elif arg.startswith("-D"):
128+
_append_definition(mkdoc_args, arg[2:])
129+
else:
130+
# append argument as is and hope for the best
131+
mkdoc_args.append(shlex.quote(arg))
60132

61-
-Dkey=value Specify a compiler definition
133+
for header in parsed_args.header:
134+
mkdoc_args.append(shlex.quote(header))
62135

63-
(Other compiler flags that Clang understands can also be supplied)""")
64-
else:
65-
mkdoc(mkdoc_args, docstring_width, mkdoc_out)
136+
mkdoc(mkdoc_args, docstring_width, mkdoc_out)
66137

67138
return 0

0 commit comments

Comments
 (0)