argparse: Add support for multiple option names to add_argument().

pull/46/merge
Delio Brignoli 2015-10-16 21:20:13 +02:00 zatwierdzone przez Damien George
rodzic b9ca8ea921
commit dd34477222
2 zmienionych plików z 43 dodań i 20 usunięć

Wyświetl plik

@ -9,8 +9,8 @@ class _ArgError(BaseException):
pass pass
class _Arg: class _Arg:
def __init__(self, name, dest, action, nargs, const, default, help): def __init__(self, names, dest, action, nargs, const, default, help):
self.name = name self.names = names
self.dest = dest self.dest = dest
self.action = action self.action = action
self.nargs = nargs self.nargs = nargs
@ -18,14 +18,14 @@ class _Arg:
self.default = default self.default = default
self.help = help self.help = help
def parse(self, args): def parse(self, optname, args):
# parse args for this arg # parse args for this arg
if self.action == "store": if self.action == "store":
if self.nargs == None: if self.nargs == None:
if args: if args:
return args.pop(0) return args.pop(0)
else: else:
raise _ArgError("expecting value for %s" % self.name) raise _ArgError("expecting value for %s" % optname)
elif self.nargs == "?": elif self.nargs == "?":
if args: if args:
return args.pop(0) return args.pop(0)
@ -36,7 +36,7 @@ class _Arg:
n = -1 n = -1
elif self.nargs == "+": elif self.nargs == "+":
if not args: if not args:
raise _ArgError("expecting value for %s" % self.name) raise _ArgError("expecting value for %s" % optname)
n = -1 n = -1
else: else:
n = int(self.nargs) n = int(self.nargs)
@ -53,20 +53,29 @@ class _Arg:
ret.append(args.pop(0)) ret.append(args.pop(0))
n -= 1 n -= 1
if n > 0: if n > 0:
raise _ArgError("expecting value for %s" % self.name) raise _ArgError("expecting value for %s" % optname)
return ret return ret
elif self.action == "store_const": elif self.action == "store_const":
return self.const return self.const
else: else:
assert False assert False
def _dest_from_optnames(opt_names):
dest = opt_names[0]
for name in opt_names:
if name.startswith("--"):
dest = name
break
return dest.lstrip("-").replace("-", "_")
class ArgumentParser: class ArgumentParser:
def __init__(self, *, description=""): def __init__(self, *, description=""):
self.description = description self.description = description
self.opt = [] self.opt = []
self.pos = [] self.pos = []
def add_argument(self, name, **kwargs): def add_argument(self, *args, **kwargs):
action = kwargs.get("action", "store") action = kwargs.get("action", "store")
if action == "store_true": if action == "store_true":
action = "store_const" action = "store_const"
@ -79,17 +88,18 @@ class ArgumentParser:
else: else:
const = kwargs.get("const", None) const = kwargs.get("const", None)
default = kwargs.get("default", None) default = kwargs.get("default", None)
if name.startswith("-"): if args and args[0].startswith("-"):
list = self.opt list = self.opt
if name.startswith("--"): dest = kwargs.get("dest")
dest = kwargs.get("dest", name[2:]) if dest is None:
else: dest = _dest_from_optnames(args)
dest = kwargs.get("dest", name[1:])
else: else:
list = self.pos list = self.pos
dest = kwargs.get("dest", name) dest = kwargs.get("dest")
if dest is None:
dest = args[0]
list.append( list.append(
_Arg(name, dest, action, kwargs.get("nargs", None), _Arg(args, dest, action, kwargs.get("nargs", None),
const, default, kwargs.get("help", ""))) const, default, kwargs.get("help", "")))
def usage(self, full): def usage(self, full):
@ -106,7 +116,7 @@ class ArgumentParser:
else: else:
return "" return ""
for opt in self.opt: for opt in self.opt:
print(" [%s%s]" % (opt.name, render_arg(opt)), end="") print(" [%s%s]" % (', '.join(opt.names), render_arg(opt)), end="")
for pos in self.pos: for pos in self.pos:
print(render_arg(pos), end="") print(render_arg(pos), end="")
print() print()
@ -120,11 +130,11 @@ class ArgumentParser:
if self.pos: if self.pos:
print("\npositional args:") print("\npositional args:")
for pos in self.pos: for pos in self.pos:
print(" %-16s%s" % (pos.name, pos.help)) print(" %-16s%s" % (pos.names[0], pos.help))
print("\noptional args:") print("\noptional args:")
print(" -h, --help show this message and exit") print(" -h, --help show this message and exit")
for opt in self.opt: for opt in self.opt:
print(" %-16s%s" % (opt.name + render_arg(opt), opt.help)) print(" %-16s%s" % (', '.join(opt.names) + render_arg(opt), opt.help))
def parse_args(self, args=None): def parse_args(self, args=None):
if args is None: if args is None:
@ -157,8 +167,8 @@ class ArgumentParser:
sys.exit(0) sys.exit(0)
found = False found = False
for i, opt in enumerate(self.opt): for i, opt in enumerate(self.opt):
if a == opt.name: if a in opt.names:
arg_vals[i] = opt.parse(args) arg_vals[i] = opt.parse(a, args)
found = True found = True
break break
if not found: if not found:
@ -169,7 +179,7 @@ class ArgumentParser:
raise _ArgError("extra args: %s" % " ".join(args)) raise _ArgError("extra args: %s" % " ".join(args))
for pos in self.pos: for pos in self.pos:
arg_dest.append(pos.dest) arg_dest.append(pos.dest)
arg_vals.append(pos.parse(args)) arg_vals.append(pos.parse(pos.names[0], args))
parsed_pos = True parsed_pos = True
# build and return named tuple with arg values # build and return named tuple with arg values

Wyświetl plik

@ -17,6 +17,19 @@ assert args.a == True and args.b == 123
args = parser.parse_args(["-b", "456"]) args = parser.parse_args(["-b", "456"])
assert args.a == False and args.b == "456" assert args.a == False and args.b == "456"
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--a-opt", action="store_true")
parser.add_argument("-b", "--b-opt", default=123)
parser.add_argument("--c-opt", default="test")
args = parser.parse_args([])
assert args.a_opt == False and args.b_opt == 123 and args.c_opt == "test"
args = parser.parse_args(["--a-opt"])
assert args.a_opt == True and args.b_opt == 123 and args.c_opt == "test"
args = parser.parse_args(["--b-opt", "456"])
assert args.a_opt == False and args.b_opt == "456" and args.c_opt == "test"
args = parser.parse_args(["--c-opt", "override"])
assert args.a_opt == False and args.b_opt == 123 and args.c_opt == "override"
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("files", nargs="+") parser.add_argument("files", nargs="+")
args = parser.parse_args(["a"]) args = parser.parse_args(["a"])