Skip to content

Commit dd34477

Browse files
dxxbdpgeorge
authored andcommitted
argparse: Add support for multiple option names to add_argument().
1 parent b9ca8ea commit dd34477

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

argparse/argparse.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ class _ArgError(BaseException):
99
pass
1010

1111
class _Arg:
12-
def __init__(self, name, dest, action, nargs, const, default, help):
13-
self.name = name
12+
def __init__(self, names, dest, action, nargs, const, default, help):
13+
self.names = names
1414
self.dest = dest
1515
self.action = action
1616
self.nargs = nargs
1717
self.const = const
1818
self.default = default
1919
self.help = help
2020

21-
def parse(self, args):
21+
def parse(self, optname, args):
2222
# parse args for this arg
2323
if self.action == "store":
2424
if self.nargs == None:
2525
if args:
2626
return args.pop(0)
2727
else:
28-
raise _ArgError("expecting value for %s" % self.name)
28+
raise _ArgError("expecting value for %s" % optname)
2929
elif self.nargs == "?":
3030
if args:
3131
return args.pop(0)
@@ -36,7 +36,7 @@ def parse(self, args):
3636
n = -1
3737
elif self.nargs == "+":
3838
if not args:
39-
raise _ArgError("expecting value for %s" % self.name)
39+
raise _ArgError("expecting value for %s" % optname)
4040
n = -1
4141
else:
4242
n = int(self.nargs)
@@ -53,20 +53,29 @@ def parse(self, args):
5353
ret.append(args.pop(0))
5454
n -= 1
5555
if n > 0:
56-
raise _ArgError("expecting value for %s" % self.name)
56+
raise _ArgError("expecting value for %s" % optname)
5757
return ret
5858
elif self.action == "store_const":
5959
return self.const
6060
else:
6161
assert False
6262

63+
def _dest_from_optnames(opt_names):
64+
dest = opt_names[0]
65+
for name in opt_names:
66+
if name.startswith("--"):
67+
dest = name
68+
break
69+
return dest.lstrip("-").replace("-", "_")
70+
71+
6372
class ArgumentParser:
6473
def __init__(self, *, description=""):
6574
self.description = description
6675
self.opt = []
6776
self.pos = []
6877

69-
def add_argument(self, name, **kwargs):
78+
def add_argument(self, *args, **kwargs):
7079
action = kwargs.get("action", "store")
7180
if action == "store_true":
7281
action = "store_const"
@@ -79,17 +88,18 @@ def add_argument(self, name, **kwargs):
7988
else:
8089
const = kwargs.get("const", None)
8190
default = kwargs.get("default", None)
82-
if name.startswith("-"):
91+
if args and args[0].startswith("-"):
8392
list = self.opt
84-
if name.startswith("--"):
85-
dest = kwargs.get("dest", name[2:])
86-
else:
87-
dest = kwargs.get("dest", name[1:])
93+
dest = kwargs.get("dest")
94+
if dest is None:
95+
dest = _dest_from_optnames(args)
8896
else:
8997
list = self.pos
90-
dest = kwargs.get("dest", name)
98+
dest = kwargs.get("dest")
99+
if dest is None:
100+
dest = args[0]
91101
list.append(
92-
_Arg(name, dest, action, kwargs.get("nargs", None),
102+
_Arg(args, dest, action, kwargs.get("nargs", None),
93103
const, default, kwargs.get("help", "")))
94104

95105
def usage(self, full):
@@ -106,7 +116,7 @@ def render_arg(arg):
106116
else:
107117
return ""
108118
for opt in self.opt:
109-
print(" [%s%s]" % (opt.name, render_arg(opt)), end="")
119+
print(" [%s%s]" % (', '.join(opt.names), render_arg(opt)), end="")
110120
for pos in self.pos:
111121
print(render_arg(pos), end="")
112122
print()
@@ -120,11 +130,11 @@ def render_arg(arg):
120130
if self.pos:
121131
print("\npositional args:")
122132
for pos in self.pos:
123-
print(" %-16s%s" % (pos.name, pos.help))
133+
print(" %-16s%s" % (pos.names[0], pos.help))
124134
print("\noptional args:")
125135
print(" -h, --help show this message and exit")
126136
for opt in self.opt:
127-
print(" %-16s%s" % (opt.name + render_arg(opt), opt.help))
137+
print(" %-16s%s" % (', '.join(opt.names) + render_arg(opt), opt.help))
128138

129139
def parse_args(self, args=None):
130140
if args is None:
@@ -157,8 +167,8 @@ def _parse_args(self, args):
157167
sys.exit(0)
158168
found = False
159169
for i, opt in enumerate(self.opt):
160-
if a == opt.name:
161-
arg_vals[i] = opt.parse(args)
170+
if a in opt.names:
171+
arg_vals[i] = opt.parse(a, args)
162172
found = True
163173
break
164174
if not found:
@@ -169,7 +179,7 @@ def _parse_args(self, args):
169179
raise _ArgError("extra args: %s" % " ".join(args))
170180
for pos in self.pos:
171181
arg_dest.append(pos.dest)
172-
arg_vals.append(pos.parse(args))
182+
arg_vals.append(pos.parse(pos.names[0], args))
173183
parsed_pos = True
174184

175185
# build and return named tuple with arg values

argparse/test_argparse.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
args = parser.parse_args(["-b", "456"])
1818
assert args.a == False and args.b == "456"
1919

20+
parser = argparse.ArgumentParser()
21+
parser.add_argument("-a", "--a-opt", action="store_true")
22+
parser.add_argument("-b", "--b-opt", default=123)
23+
parser.add_argument("--c-opt", default="test")
24+
args = parser.parse_args([])
25+
assert args.a_opt == False and args.b_opt == 123 and args.c_opt == "test"
26+
args = parser.parse_args(["--a-opt"])
27+
assert args.a_opt == True and args.b_opt == 123 and args.c_opt == "test"
28+
args = parser.parse_args(["--b-opt", "456"])
29+
assert args.a_opt == False and args.b_opt == "456" and args.c_opt == "test"
30+
args = parser.parse_args(["--c-opt", "override"])
31+
assert args.a_opt == False and args.b_opt == 123 and args.c_opt == "override"
32+
2033
parser = argparse.ArgumentParser()
2134
parser.add_argument("files", nargs="+")
2235
args = parser.parse_args(["a"])

0 commit comments

Comments
 (0)