Commits

S. Joshua Swamidass committed 1c604ba

working

  • Participants

Comments (0)

Files changed (1)

File confargparse.py

+import argparse
+import ConfigParser
+import sys
+from types import MethodType
+
+def _add_argument(self, *args, **kwargs):
+        chars = self.prefix_chars
+        if not args or len(args) == 1 and args[0][0] not in chars:
+            my_kwargs = self._get_positional_kwargs(*args, **kwargs)
+        else:
+            my_kwargs = self._get_optional_kwargs(*args, **kwargs)
+
+        dest = my_kwargs["dest"]
+
+        section = my_kwargs.get("conf_section", "defaults")
+        name = my_kwargs.get("conf_name", dest)
+        tipe = my_kwargs.get("conf_type", my_kwargs.get("type",str))
+        exclude = my_kwargs.get("conf_exclude", False)
+
+        if "conf_section" in kwargs: del kwargs["conf_section"]
+        if "conf_name" in kwargs: del kwargs["conf_name"]
+        if "conf_type" in kwargs: del kwargs["conf_type"]
+        if "conf_exclude" in kwargs: del kwargs["conf_exclude"]
+
+        if not exclude: self.add_mapping(dest, section, name, tipe)
+
+        return argparse._ActionsContainer.add_argument(self, *args, **kwargs)
+
+def _add_parser(self, *args, **kwargs):
+    parser = _prior_add_parser(self, *args, **kwargs)
+    parser.add_mapping = self.add_mapping
+    return parser
+
+_prior_add_parser = argparse._SubParsersAction.add_parser
+argparse._SubParsersAction.add_parser = _add_parser
+
+class ConfArgParser(argparse.ArgumentParser):
+    def __init__(self, *args, **kwargs):
+        ckwargs = dict(kwargs)
+        ckwargs["add_help"] = False
+        self.conf_parser = argparse.ArgumentParser( *args, **ckwargs )
+        group = self.conf_parser.add_argument_group("configuration file options")
+        group.add_argument("-c", "--conf_file",  help="specify config files", nargs="+", metavar="FILE")
+        group.add_argument("--export_conf_file", help="translate arguments into a config file",
+                metavar="FILE", const=sys.stdout, default=None, nargs="?", type=argparse.FileType('w'))
+
+        self._added_config_args = False
+        kwargs["formatter_class"] = argparse.RawDescriptionHelpFormatter
+
+        self.config_mapping = {}
+        self.dest_mapping = {}
+
+        argparse.ArgumentParser.__init__(self,*args, **kwargs)
+
+    add_argument = _add_argument
+
+    def add_argument_group(self, *args, **kwargs):
+        import types
+        group = argparse.ArgumentParser.add_argument_group(self, *args, **kwargs)
+        group.add_argument = MethodType(_add_argument, group, group.__class__)
+        group.add_mapping = self.add_mapping
+        return group
+
+    def add_subparsers(self, *args, **kwargs):
+        parser = argparse.ArgumentParser.add_subparsers(self, *args, **kwargs)
+        parser.add_mapping = self.add_mapping
+        return parser
+
+    def add_mutually_exclusive_groupi(self, *args, **kwargs):
+        group = argparse.ArgumentParser.add_mutually_exclusive_group(self, *args, **kwargs)
+        group.add_argument = MethodType(_add_argument, group, group.__class__)
+        group.add_mapping = self.add_mapping
+        return group
+
+    def add_mapping(self, dest, section, name, type=str, warn=True):
+        name = name.lower()
+        section = section.lower()
+
+        if warn and (section, name) in self.dest_mapping:
+            d,t = self.dest_mapping[(section, name)]
+            if d!= dest:
+                raise ValueError("Changing destination of this config address!")
+        if warn and dest in self.config_mapping:
+            s,n,t = self.config_mapping[dest]
+            if s != section or n != name:
+                raise ValueError("Changing config address of this destination!")
+
+        self.config_mapping[dest] = (section, name, type)
+        self.dest_mapping[(section, name)] = (dest, type)
+
+    def config2dest(self, config):
+        args = {}
+        for dest, (section, name, tipe) in self.config_mapping.items():
+            try: val = tipe(config.get(section, name))
+            except: continue
+            if val == "<stdin>": args[dest] = sys.stdin
+            elif val == "<stdout>": args[dest] = sys.stdout
+            elif val != "":  args[dest] = tipe(val)
+        return args
+
+    def args2config(self, args=sys.argv[1:]):
+        args = self.parse_args(args)
+        config = ConfigParser.RawConfigParser()
+        sections = set()
+        config.add_section("defaults")
+
+        for dest, (section, name, tipe) in self.config_mapping.items():
+            if section not in sections and section.lower() != "defaults": config.add_section(section)
+            try: a = args.__getattribute__(dest)
+            except: continue
+
+            if type(a) == file: val = a.name
+            else: val = a
+
+            if val == None: config.set(section, name, "")
+            else: config.set(section, name, val)
+
+        return config
+
+    def _add_config_args(self):
+        if not self._added_config_args:
+           self._added_config_args=True
+           if self._subparsers == None: self._add_container_actions(self.conf_parser)
+
+    def _parse_config(self, args):
+        args, remaining_argv = self.conf_parser.parse_known_args(args)
+
+        if args.conf_file:
+            config = ConfigParser.SafeConfigParser()
+            config.read(args.conf_file)
+            config_options = self.config2dest(config)
+            self.set_defaults(**config_options)
+        if args.export_conf_file:
+            self.args2config(remaining_argv).write(args.export_conf_file)
+            sys.exit(0)
+        return remaining_argv
+
+    def parse_known_args(self, args=sys.argv[1:], namespace=None):
+        self._add_config_args()
+        args = self._parse_config(args)
+        return argparse.ArgumentParser.parse_known_args(self, args, namespace)
+
+    def parse_args(self, args=sys.argv[1:], namespace=None):
+        self._add_config_args()
+        args = self._parse_config(args)
+        return argparse.ArgumentParser.parse_args(self, args, namespace)
+
+
+
+parser = ConfArgParser()
+#parser.add_argument("--option1", default=None, conf_section="opt1", dest="opt11", help="some option")
+#parser.add_argument("--option2", default=sys.stdin, help="some other option")
+group = parser.add_argument_group("test group")
+group.add_argument("-f", type=int)
+
+subparsers = parser.add_subparsers(help='sub-command help')
+parser_a = subparsers.add_parser('a', help='a help')
+parser_a.add_argument('bar', type=int, help='bar help')
+
+parser_b = subparsers.add_parser('b', help='b help')
+parser_b.add_argument('--baz', choices='XYZ', help='baz help')
+
+parser.args2config().write(sys.stdout)
+print parser.parse_args()