Commits

Anonymous committed 72f8d74 Draft

nice config block output

Comments (0)

Files changed (2)

argparse_config.src/argparse_config/__init__.py

 """
 import ConfigParser
 from argparse import _SubParsersAction, _StoreAction, _StoreConstAction
+import argparse
 
 __version__ = '0.5'
 
 
-def read_config_file(arg_parser, filename):
+def get_config_parser(filename):
     config_parser = ConfigParser.SafeConfigParser(allow_no_value=True)
     config_parser.read([filename])
+    return config_parser
+
+
+def read_config_file(arg_parser, filename):
+    config_parser = get_config_parser(filename)
     read_config_parser(arg_parser, config_parser)
 
 
     ReadConfig(config_parser=config_parser).walk_parser(arg_parser)
 
 
+def add_config_block_subcommand(arg_parser, subparsers=None, config_parser=None,
+                                dest='command',
+                                only_non_defaults=False):
+    """
+    Add a subcommand "config-block" to the arg_parser, to be used as follows:
+
+    In myprog.py:
+
+    add_config_block_subcommand(arg_parser) # if no other subcommands defined
+    add_config_block_subcommand(arg_parser, subparsers=subparsers) # if subcommands defined on subparsers obj
+    # ...
+    parsed_args = arg_parser.parse_args()
+    if parsed_args.command == 'config':
+        print parsed_args.func(parsed_args)
+        exit(0)
+
+    On the commandline:
+
+    $ myprog.py config default --username tikitu --secret xyzzy
+    [default]
+    username: tikitu
+    secret: xyzzy
+
+    :param arg_parser:
+    :param config_parser:
+    :param dest:
+    :param only_non_defaults:
+    :return: None
+    """
+    if subparsers is None:
+        subparsers = arg_parser.add_subparsers(title='config file management',
+                                               dest=dest)
+    subparser = subparsers.add_parser('config')
+    subparser.add_argument('block')
+    subparser.add_argument('commandline', nargs=argparse.REMAINDER)
+
+    def handle_args(orig_parsed_args):
+        if config_parser is not None:
+            read_config_parser(arg_parser, config_parser)
+        args_for_commandline = list(orig_parsed_args.commandline)
+        if orig_parsed_args.block == 'default':
+            subparsers.add_parser('dummy-command')
+            args_for_commandline.append('dummy-command')
+        else:
+            args_for_commandline.insert(0, orig_parsed_args.block)
+        parsed_args = arg_parser.parse_args(args_for_commandline)
+        return generate_config(arg_parser, parsed_args,
+                               section=orig_parsed_args.block,
+                               only_non_defaults=only_non_defaults)
+
+    subparser.set_defaults(func=handle_args)
+
+
 def generate_config(arg_parser, parsed_args, section='default',
                     only_non_defaults=False):
     action = GenerateConfig(parsed_args, section,
         self._contents = []
         self._only_non_defaults = only_non_defaults
         self._section = section
-        self._in_section = False
+        self._in_sections = []
 
     def start_section(self, section_name):
+        self._in_sections.append(section_name)
         if section_name == self._section:
-            self._in_section = True
             if self._contents:
                 self._contents.append(u'')
             self._contents.append(u'[{0}]'.format(section_name))
 
     def end_section(self):
-        self._in_section = False
+        self._in_sections.pop()
 
     @property
     def contents(self):
         return u'\n'.join(self._contents + [u''])
 
     def process_parser_action(self, action, is_store_const=False):
-        if not self._in_section:
+        if self._in_sections[-1] != self._section:
             return
-            # take the longest string, likely the most informative
+        # take the longest string, likely the most informative
         action_name = list(action.option_strings)
         action_name.sort(key=lambda s: len(s), reverse=True)
         action_name = _convert_option_string(action_name[0])

argparse_config.src/argparse_config/tests/__init__.py

 import tempfile
 import textwrap
 from unittest import TestCase
-from .. import read_config_parser, read_config_file, generate_config
+from .. import read_config_parser, read_config_file, generate_config, add_config_block_subcommand
 
 __author__ = 'tikitu'
 
         [default]
         str_value: ssss
         """.lstrip('\n')))
+
+
+class SubcommandTest(TestCase):
+
+    def get_arg_and_sub_parsers(self):
+        arg_parser = ArgumentParser('hg')
+        arg_parser.add_argument('--repository')
+        subparsers = arg_parser.add_subparsers(dest='command')
+
+        merge_parser = subparsers.add_parser('merge')
+        merge_parser.add_argument('--tool')
+
+        commit_parser = subparsers.add_parser('commit')
+        commit_parser.add_argument('--user')
+
+        return arg_parser, subparsers
+
+    def test_subcommand(self):
+        arg_parser, subparsers = self.get_arg_and_sub_parsers()
+
+        add_config_block_subcommand(arg_parser, subparsers=subparsers)
+
+        parsed_args = arg_parser.parse_args('config default --repository somewhere'.split())
+        self.assertEquals(parsed_args.command, 'config')
+        self.assertEquals(parsed_args.func(parsed_args), textwrap.dedent("""
+        [default]
+        repository: somewhere
+        """.lstrip('\n')))
+
+        parsed_args = arg_parser.parse_args('config merge --tool nothing'.split())
+        self.assertEquals(parsed_args.command, 'config')
+        self.assertEquals(parsed_args.func(parsed_args), textwrap.dedent("""
+        [merge]
+        tool: nothing
+        """.lstrip('\n')))
+
+    @with_config_file()
+    def test_subcommand_with_config_file(self, config_parser):
+        """
+        [default]
+        repository: somewhere
+        """
+        arg_parser, subparsers = self.get_arg_and_sub_parsers()
+        arg_parser.add_argument('--some-arg')
+
+        add_config_block_subcommand(arg_parser, subparsers=subparsers, config_parser=config_parser)
+
+        parsed_args = arg_parser.parse_args('config default --some-arg value'.split())
+        self.assertEquals(parsed_args.command, 'config')
+        self.assertEquals(parsed_args.func(parsed_args), textwrap.dedent("""
+        [default]
+        repository: somewhere
+        some_arg: value
+        """.lstrip('\n')))