From d0b5daad4f6eff01c3819d5236c60ae71e877a73 Mon Sep 17 00:00:00 2001 From: rod-lin Date: Sun, 15 Sep 2019 00:16:48 -0500 Subject: [PATCH] fix positional arguments --- flagset/__init__.py | 24 +++++++++++++++++++----- tests/test_basic.py | 11 +++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/flagset/__init__.py b/flagset/__init__.py index 6a1d096..63a9abd 100644 --- a/flagset/__init__.py +++ b/flagset/__init__.py @@ -59,6 +59,7 @@ def __init__( assert ( cmdline_name is not None or env_name is not None or config_name is not None ), "expecting at least one flag name" + assert ( default is None or not required ), "cannot provide default value for required flag" @@ -70,6 +71,9 @@ def __init__( self.default = default self.help = help self.required = required + self.positional = isinstance(cmdline_name, str) and not cmdline_name.startswith( + "-" + ) def _parse_env(self, env): if self.env_name is not None and self.env_name in env: @@ -87,7 +91,7 @@ def _bind_argparser(self, parser, dest=None): kwargs = {} - if dest is not None: + if dest is not None and not self.positional: kwargs["dest"] = dest # help message: [. default value ''][. env var ''] @@ -157,8 +161,6 @@ class FlagSet: 5. optional help message """ - INTERNAL_FLAG_CONFIG = "config" - def __init__(self, init_set={}): """ :params config_parser: should take a string and return dict @@ -179,7 +181,6 @@ def _parse_cmdline(self, args): res = {} parser = _ArgumentParserWithException(add_help=False) - parser.add_argument("__config", nargs="?") parser.add_argument( "--help", "-h", dest="__help", action="store_true", default=False ) @@ -190,8 +191,20 @@ def _parse_cmdline(self, args): if flag.cmdline_name is not None: flag._bind_argparser(parser, canon) + # bind config flag last + parser.add_argument("__config", nargs="?") + parsed = vars(parser.parse_args(args)) + for canon, flag in self.flags.items(): + if ( + flag.positional + and flag.cmdline_name in parsed + and canon != flag.cmdline_name + ): + parsed[canon] = parsed[flag.cmdline_name] + del parsed[flag.cmdline_name] + if parsed["__help"]: raise FlagHelp() @@ -262,11 +275,12 @@ def parse( def print_help(self): parser = argparse.ArgumentParser() - parser.add_argument("config", nargs="?", help="config file") for flag in self.flags.values(): flag._bind_argparser(parser) + parser.add_argument("config", nargs="?", help="config file") + parser.print_help(file=sys.stderr) # show other flags diff --git a/tests/test_basic.py b/tests/test_basic.py index e69e5a5..5a1d03e 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -68,3 +68,14 @@ def test_precedence(self): use_exc=True, ) self.assertEqual(flags["flag"], "from cmd") + + def test_positional(self): + fset = FlagSet( + {"flag": Flag(cmdline_name="flag-name")} + ) + + flags = fset.parse( + args=["from_cmd"], use_exc=True + ) + self.assertEqual(flags["flag"], "from_cmd") + self.assertNotIn("flag-name", flags)