Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-configargparse for 
openSUSE:Factory checked in at 2021-07-12 01:25:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-configargparse (Old)
 and      /work/SRC/openSUSE:Factory/.python-configargparse.new.2625 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-configargparse"

Mon Jul 12 01:25:14 2021 rev:13 rq:905704 version:1.5.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-configargparse/python-configargparse.changes  
    2021-06-09 21:52:48.926529642 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-configargparse.new.2625/python-configargparse.changes
    2021-07-12 01:25:35.128978103 +0200
@@ -1,0 +2,6 @@
+Sun Jul  4 19:52:10 UTC 2021 - Dirk M??ller <dmuel...@suse.com>
+
+- update to 1.5.1:
+  * no changes file available 
+
+-------------------------------------------------------------------

Old:
----
  ConfigArgParse-1.3.tar.gz

New:
----
  ConfigArgParse-1.5.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-configargparse.spec ++++++
--- /var/tmp/diff_new_pack.Hace3N/_old  2021-07-12 01:25:35.500975243 +0200
+++ /var/tmp/diff_new_pack.Hace3N/_new  2021-07-12 01:25:35.504975212 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %bcond_without python2
 Name:           python-configargparse
-Version:        1.3
+Version:        1.5.1
 Release:        0
 Summary:        A drop-in replacement for argparse
 License:        MIT

++++++ ConfigArgParse-1.3.tar.gz -> ConfigArgParse-1.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/ConfigArgParse.egg-info/PKG-INFO 
new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/PKG-INFO
--- old/ConfigArgParse-1.3/ConfigArgParse.egg-info/PKG-INFO     2021-02-15 
00:17:35.000000000 +0100
+++ new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/PKG-INFO   2021-07-01 
15:11:14.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: ConfigArgParse
-Version: 1.3
+Version: 1.5.1
 Summary: A drop-in replacement for argparse that allows options to also be set 
via config files and/or environment variables.
 Home-page: https://github.com/bw2/ConfigArgParse
 License: MIT
@@ -95,7 +95,7 @@
         
         .. code:: py
         
-            # settings for my_script.py
+            # settings for config_test.py
             genome = HCMV     # cytomegalovirus genome
             dbsnp = /data/dbsnp/variants.vcf
         
@@ -486,7 +486,9 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
+Provides-Extra: test
 Provides-Extra: yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ConfigArgParse-1.3/ConfigArgParse.egg-info/SOURCES.txt 
new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/SOURCES.txt
--- old/ConfigArgParse-1.3/ConfigArgParse.egg-info/SOURCES.txt  2021-02-15 
00:17:36.000000000 +0100
+++ new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/SOURCES.txt        
2021-07-01 15:11:14.000000000 +0200
@@ -10,5 +10,4 @@
 ConfigArgParse.egg-info/top_level.txt
 tests/__init__.py
 tests/__init__.pyc
-tests/test_configargparse.py
-tests/test_configargparse.pyc
\ No newline at end of file
+tests/test_configargparse.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ConfigArgParse-1.3/ConfigArgParse.egg-info/requires.txt 
new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/requires.txt
--- old/ConfigArgParse-1.3/ConfigArgParse.egg-info/requires.txt 2021-02-15 
00:17:35.000000000 +0100
+++ new/ConfigArgParse-1.5.1/ConfigArgParse.egg-info/requires.txt       
2021-07-01 15:11:14.000000000 +0200
@@ -1,3 +1,8 @@
 
+[test]
+mock
+PyYAML
+pytest
+
 [yaml]
 PyYAML
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/PKG-INFO 
new/ConfigArgParse-1.5.1/PKG-INFO
--- old/ConfigArgParse-1.3/PKG-INFO     2021-02-15 00:17:36.000000000 +0100
+++ new/ConfigArgParse-1.5.1/PKG-INFO   2021-07-01 15:11:14.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: ConfigArgParse
-Version: 1.3
+Version: 1.5.1
 Summary: A drop-in replacement for argparse that allows options to also be set 
via config files and/or environment variables.
 Home-page: https://github.com/bw2/ConfigArgParse
 License: MIT
@@ -95,7 +95,7 @@
         
         .. code:: py
         
-            # settings for my_script.py
+            # settings for config_test.py
             genome = HCMV     # cytomegalovirus genome
             dbsnp = /data/dbsnp/variants.vcf
         
@@ -486,7 +486,9 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
+Provides-Extra: test
 Provides-Extra: yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/README.rst 
new/ConfigArgParse-1.5.1/README.rst
--- old/ConfigArgParse-1.3/README.rst   2021-02-14 23:41:31.000000000 +0100
+++ new/ConfigArgParse-1.5.1/README.rst 2021-05-10 21:38:05.000000000 +0200
@@ -89,7 +89,7 @@
 
 .. code:: py
 
-    # settings for my_script.py
+    # settings for config_test.py
     genome = HCMV     # cytomegalovirus genome
     dbsnp = /data/dbsnp/variants.vcf
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/configargparse.py 
new/ConfigArgParse-1.5.1/configargparse.py
--- old/ConfigArgParse-1.3/configargparse.py    2021-02-15 00:09:27.000000000 
+0100
+++ new/ConfigArgParse-1.5.1/configargparse.py  2021-07-01 15:10:04.000000000 
+0200
@@ -6,6 +6,7 @@
 import sys
 import types
 from collections import OrderedDict
+import textwrap
 
 if sys.version_info >= (3, 0):
     from io import StringIO
@@ -82,8 +83,8 @@
             stream: A config file input stream (such as an open file object).
 
         Returns:
-            OrderedDict of items where the keys have type string and the
-            values have type either string or list (eg. to support config file
+            OrderedDict: Items where the keys are strings and the
+            values are either strings or lists (eg. to support config file
             formats like YAML which allow lists).
         """
         raise NotImplementedError("parse(..) not implemented")
@@ -94,8 +95,8 @@
 
         Args:
             items: an OrderedDict of items to be converted to the config file
-            format. Keys should be strings, and values should be either strings
-            or lists.
+                format. Keys should be strings, and values should be either 
strings
+                or lists.
 
         Returns:
             Contents of config file as a string
@@ -109,7 +110,7 @@
 
 class DefaultConfigFileParser(ConfigFileParser):
     """Based on a simplified subset of INI and YAML formats. Here is the
-    supported syntax:
+    supported syntax::
 
 
         # this is a comment
@@ -148,22 +149,19 @@
             line = line.strip()
             if not line or line[0] in ["#", ";", "["] or 
line.startswith("---"):
                 continue
-            white_space = "\\s*"
-            key = r"(?P<key>[^:=;#\s]+?)"
-            value = white_space+r"[:=\s]"+white_space+"(?P<value>.+?)"
-            comment = white_space+"(?P<comment>\\s[;#].*)?"
-
-            key_only_match = re.match("^" + key + comment + "$", line)
-            if key_only_match:
-                key = key_only_match.group("key")
-                items[key] = "true"
-                continue
-
-            key_value_match = re.match("^"+key+value+comment+"$", line)
-            if key_value_match:
-                key = key_value_match.group("key")
-                value = key_value_match.group("value")
 
+            match = re.match(r'^(?P<key>[^:=;#\s]+)\s*'
+                             
r'(?:(?P<equal>[:=\s])\s*([\'"]?)(?P<value>.+?)?\3)?'
+                             r'\s*(?:\s[;#]\s*(?P<comment>.*?)\s*)?$', line)
+            if match:
+                key = match.group("key")
+                equal = match.group('equal')
+                value = match.group("value")
+                comment = match.group("comment")
+                if value is None and equal is not None and equal != ' ':
+                    value = ''
+                elif value is None:
+                    value = "true"
                 if value.startswith("[") and value.endswith("]"):
                     # handle special case of k=[1,2,3] or other json-like 
syntax
                     try:
@@ -171,13 +169,12 @@
                     except Exception as e:
                         # for backward compatibility with legacy format (eg. 
where config value is [a, b, c] instead of proper json ["a", "b", "c"]
                         value = [elem.strip() for elem in 
value[1:-1].split(",")]
-
+                if comment:
+                    comment = comment.strip()[1:].strip()
                 items[key] = value
-                continue
-
-
-            raise ConfigFileParserException("Unexpected line {} in {}: 
{}".format(i,
-                getattr(stream, 'name', 'stream'), line))
+            else:
+                raise ConfigFileParserException("Unexpected line {} in {}: 
{}".format(i,
+                    getattr(stream, 'name', 'stream'), line))
         return items
 
     def serialize(self, items):
@@ -230,6 +227,7 @@
             config.read_string(stream.read())
         except Exception as e:
             raise ConfigFileParserException("Couldn't parse config file: %s" % 
e)
+
         # convert to dict and remove INI section names
         result = OrderedDict()
         for section in config.sections():
@@ -259,13 +257,14 @@
             strict=True,
             empty_lines_in_values=False,
         )
-        items = {"DEFAULT":items}
+        items = {"DEFAULT": items}
         config.read_dict(items)
         stream = io.StringIO()
         config.write(stream)
         stream.seek(0)
         return stream.read()
 
+
 class YAMLConfigFileParser(ConfigFileParser):
     """Parses YAML config files. Depends on the PyYAML module.
     https://pypi.python.org/pypi/PyYAML
@@ -313,7 +312,6 @@
 
         return result
 
-
     def serialize(self, items, default_flow_style=False):
         """Does the inverse of config parsing by taking parsed values and
         converting them back to a string representing config file contents.
@@ -344,10 +342,10 @@
 
     def __init__(self, *args, **kwargs):
 
-        """Supports args of the argparse.ArgumentParser constructor
-        as **kwargs, as well as the following additional args.
+        r"""Supports args of the argparse.ArgumentParser constructor
+        as \*\*kwargs, as well as the following additional args.
 
-        Additional Args:
+        Arguments:
             add_config_file_help: Whether to add a description of config file
                 syntax to the help message.
             add_env_var_help: Whether to add something to the help message for
@@ -363,12 +361,14 @@
                 taking precedence over previous ones. This allows an 
application
                 to look for config files in multiple standard locations such as
                 the install directory, home directory, and current directory.
-                Also, shell * syntax can be used to specify all conf files in a
-                directory. For example:
-                ["/etc/conf/app_config.ini",
-                 "/etc/conf/conf-enabled/*.ini",
-                "~/.my_app_config.ini",
-                "./app_config.txt"]
+                Also, shell \* syntax can be used to specify all conf files in 
a
+                directory. For example::
+
+                    ["/etc/conf/app_config.ini",
+                    "/etc/conf/conf-enabled/*.ini",
+                    "~/.my_app_config.ini",
+                    "./app_config.txt"]
+
             ignore_unknown_config_file_keys: If true, settings that are found
                 in a config file but don't correspond to any defined
                 configargparse args will be ignored. If false, they will be
@@ -451,29 +451,39 @@
         """Supports all the same args as the ArgumentParser.parse_args(..),
         as well as the following additional args.
 
-        Additional Args:
+        Arguments:
             args: a list of args as in argparse, or a string (eg. "-x -y bla")
             config_file_contents: String. Used for testing.
             env_vars: Dictionary. Used for testing.
         """
-        args, argv = self.parse_known_args(args = args,
-            namespace = namespace,
-            config_file_contents = config_file_contents,
-            env_vars = env_vars)
+        args, argv = self.parse_known_args(
+            args=args,
+            namespace=namespace,
+            config_file_contents=config_file_contents,
+            env_vars=env_vars,
+            ignore_help_args=False)
+
         if argv:
             self.error('unrecognized arguments: %s' % ' '.join(argv))
         return args
 
-
-    def parse_known_args(self, args = None, namespace = None,
-                         config_file_contents = None, env_vars = os.environ):
+    def parse_known_args(
+            self,
+            args=None,
+            namespace=None,
+            config_file_contents=None,
+            env_vars=os.environ,
+            ignore_help_args=False,
+    ):
         """Supports all the same args as the ArgumentParser.parse_args(..),
         as well as the following additional args.
 
-        Additional Args:
+        Arguments:
             args: a list of args as in argparse, or a string (eg. "-x -y bla")
-            config_file_contents: String. Used for testing.
-            env_vars: Dictionary. Used for testing.
+            config_file_contents (str). Used for testing.
+            env_vars (dict). Used for testing.
+            ignore_help_args (bool): This flag determines behavior when user 
specifies --help or -h. If False,
+                it will have the default behavior - printing help and exiting. 
If True, it won't do either.
         """
         if args is None:
             args = sys.argv[1:]
@@ -485,6 +495,9 @@
         for a in self._actions:
             a.is_positional_arg = not a.option_strings
 
+        if ignore_help_args:
+            args = [arg for arg in args if arg not in ("-h", "--help")]
+
         # maps a string describing the source (eg. env var) to a settings dict
         # to keep track of where values came from (used by print_values()).
         # The settings dicts for env vars and config files will then map
@@ -628,6 +641,20 @@
         self.write_config_file(namespace, output_file_paths, exit_after=True)
         return namespace, unknown_args
 
+    def get_source_to_settings_dict(self):
+        """If called after parse_args() or parse_known_args(), this dict. will 
contain up to 4 keys corresponding
+        to where a given option's value is coming from:
+            "command_line"
+            "environment_variables"
+            "config_file"
+            "defaults"
+        Each such key, will be mapped to another dictionary containing the 
options set via that method. Here the key
+        will be the option name, and the value will be a 2-tuple of the form 
(argparse Action obj, string value).
+        """
+
+        return self._source_to_settings
+
+
     def write_config_file(self, parsed_namespace, output_file_paths, 
exit_after=False):
         """Write the given settings to output files.
 
@@ -652,12 +679,10 @@
             for output_file_path in output_file_paths:
                 with self._config_file_open_func(output_file_path, "w") as 
output_file:
                     output_file.write(file_contents)
-            message = "Wrote config file to " + ", ".join(output_file_paths)
-            if exit_after:
-                self.exit(0, message)
-            else:
-                print(message)
 
+            print("Wrote config file to " + ", ".join(output_file_paths))
+            if exit_after:
+                self.exit(0)
 
     def get_command_line_key_for_unknown_config_file_setting(self, key):
         """Compute a commandline arg key to be used for a config file setting
@@ -681,7 +706,7 @@
             source_to_settings: the dictionary described in parse_known_args()
             parsed_namespace: namespace object created within 
parse_known_args()
         Returns:
-            an OrderedDict where keys are strings and values are either strings
+            OrderedDict: where keys are strings and values are either strings
             or lists
         """
         config_file_items = OrderedDict()
@@ -745,6 +770,11 @@
             elif value.lower() in ("false", "no", "0"):
                 # don't append when set to "false" / "no"
                 pass
+            elif isinstance(action, argparse._CountAction):
+                for arg in args:
+                    if any([arg.startswith(s) for s in action.option_strings]):
+                        value = 0
+                args += [action.option_strings[0]] * int(value)
             else:
                 self.error("Unexpected value for %s: '%s'. Expecting 'true', "
                            "'false', 'yes', 'no', '1' or '0'" % (key, value))
@@ -795,7 +825,6 @@
 
         return keys
 
-
     def _open_config_files(self, command_line_args):
         """Tries to parse config file path(s) from within command_line_args.
         Returns a list of opened config files, including files specified on the
@@ -854,6 +883,12 @@
                     errno, msg = e.args
                 else:
                     msg = str(e)
+                # close previously opened config files
+                for config_file in config_files:
+                    try:
+                        config_file.close()
+                    except Exception:
+                        pass
                 self.error("Unable to open config file: %s. Error: %s" % (
                     user_config_file, msg
                 ))
@@ -946,10 +981,12 @@
             msg += (" If an arg is specified in more than one place, then "
                 "commandline values override %s.") % (
                 " which override ".join(value_sources))
-        if msg:
-            self.description = (self.description or "") + " " + msg
 
-        return argparse.ArgumentParser.format_help(self)
+        text_width = max(self._get_formatter()._width, 11)
+        msg = textwrap.fill(msg, text_width)
+
+        return (argparse.ArgumentParser.format_help(self)
+              + ("\n{}\n".format(msg) if msg != "" else ""))
 
 
 def add_argument(self, *args, **kwargs):
@@ -957,7 +994,7 @@
     This method supports the same args as ArgumentParser.add_argument(..)
     as well as the additional args below.
 
-    Additional Args:
+    Arguments:
         env_var: If set, the value of this environment variable will override
             any config file or default values for this arg (but can itself
             be overridden on the commandline). Also, if auto_env_var_prefix is
@@ -1018,6 +1055,12 @@
         else:
             arg_names.append(arg_string)
 
+    """
+    return any(
+        arg_name.startswith(potential_arg) for potential_arg in 
potential_command_line_args for arg_name in arg_names
+    )
+    # TODO: need to support allow_abbrev, exit_on.. new args etc.
+    """
     return any(
         potential_arg in arg_names for potential_arg in 
potential_command_line_args
     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/setup.py 
new/ConfigArgParse-1.5.1/setup.py
--- old/ConfigArgParse-1.3/setup.py     2021-02-15 00:14:13.000000000 +0100
+++ new/ConfigArgParse-1.5.1/setup.py   2021-07-01 14:41:49.000000000 +0200
@@ -49,7 +49,10 @@
 
 command = sys.argv[-1]
 if command == 'publish':
-    os.system('python setup.py sdist upload')
+    os.system('rm -rf dist')    
+    os.system('python setup.py sdist')
+    os.system('python3 setup.py bdist_wheel')
+    os.system('twine upload dist/*whl dist/*gz')
     sys.exit()
 elif command == "coverage":
     try:
@@ -70,13 +73,15 @@
 
 install_requires = []
 tests_require = [
+    'mock',
     'PyYAML',
+    'pytest',
 ]
 
 
 setup(
     name='ConfigArgParse',
-    version="1.3",
+    version="1.5.1",
     description='A drop-in replacement for argparse that allows options to '
                 'also be set via config files and/or environment variables.',
     long_description=long_description,
@@ -99,6 +104,7 @@
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
     ],
@@ -108,5 +114,6 @@
     tests_require=tests_require,
     extras_require = {
         'yaml': ["PyYAML"],
+        'test': tests_require,
     }
 )
Binary files old/ConfigArgParse-1.3/tests/__init__.pyc and 
new/ConfigArgParse-1.5.1/tests/__init__.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ConfigArgParse-1.3/tests/test_configargparse.py 
new/ConfigArgParse-1.5.1/tests/test_configargparse.py
--- old/ConfigArgParse-1.3/tests/test_configargparse.py 2021-02-14 
23:41:54.000000000 +0100
+++ new/ConfigArgParse-1.5.1/tests/test_configargparse.py       2021-07-01 
15:04:28.000000000 +0200
@@ -19,6 +19,11 @@
 else:
     from StringIO import StringIO
 
+if sys.version_info >= (3, 10):
+    OPTIONAL_ARGS_STRING="options"
+else:
+    OPTIONAL_ARGS_STRING="optional arguments"
+
 # set COLUMNS to get expected wrapping
 os.environ['COLUMNS'] = '80'
 
@@ -35,7 +40,7 @@
     def error_method(self, message):
         raise argparse.ArgumentError(None, message)
 
-    def exit_method(self, status, message):
+    def exit_method(self, status, message=None):
         self._exit_method_called = True
 
     arg_parser._exit_method_called = False
@@ -77,9 +82,9 @@
 
         return self.parser
 
-    def assertParseArgsRaises(self, regex, *args, **kwargs):
+    def assertParseArgsRaises(self, regex, args, **kwargs):
         self.assertRaisesRegex(argparse.ArgumentError, regex, self.parse,
-                               *args, **kwargs)
+                               args=args, **kwargs)
 
 
 class TestBasicUseCases(TestCase):
@@ -249,25 +254,24 @@
         if not use_groups:
             self.assertRegex(self.format_help(),
                 'usage: .* \\[-h\\] --genome GENOME \\[-v\\] -g MY_CFG_FILE\n?'
-                '\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\n' 
+
-                9*r'(.+\s+)'+  # repeated 8 times because .+ matches atmost 1 
line
+                '\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\n'
                 'positional arguments:\n'
                 '  vcf \\s+ Variant file\\(s\\)\n\n'
-                'optional arguments:\n'
+                '%s:\n'
                 '  -h, --help \\s+ show this help message and exit\n'
                 '  --genome GENOME \\s+ Path to genome file\n'
                 '  -v\n'
                 '  -g MY_CFG_FILE, --my-cfg-file MY_CFG_FILE\n'
                 '  -d DBSNP, --dbsnp DBSNP\\s+\\[env var: DBSNP_PATH\\]\n'
-                '  -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n')
+                '  -f FRMT, --format FRMT\\s+\\[env var: 
OUTPUT_FORMAT\\]\n\n'%OPTIONAL_ARGS_STRING +
+                7*r'(.+\s*)')
         else:
             self.assertRegex(self.format_help(),
                 'usage: .* \\[-h\\] --genome GENOME \\[-v\\] -g MY_CFG_FILE\n?'
-                '\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\n'+
-                9*r'.+\s+'+  # repeated 8 times because .+ matches atmost 1 
line
+                '\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\n'
                 'positional arguments:\n'
                 '  vcf \\s+ Variant file\\(s\\)\n\n'
-                'optional arguments:\n'
+                '%s:\n'
                 '  -h, --help \\s+ show this help message and exit\n\n'
                 'g1:\n'
                 '  --genome GENOME \\s+ Path to genome file\n'
@@ -275,7 +279,8 @@
                 '  -g MY_CFG_FILE, --my-cfg-file MY_CFG_FILE\n\n'
                 'g2:\n'
                 '  -d DBSNP, --dbsnp DBSNP\\s+\\[env var: DBSNP_PATH\\]\n'
-                '  -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n')
+                '  -f FRMT, --format FRMT\\s+\\[env var: 
OUTPUT_FORMAT\\]\n\n'%OPTIONAL_ARGS_STRING +
+                7*r'(.+\s*)')
 
         self.assertParseArgsRaises("invalid choice: 'ZZZ'",
             args="--genome hg19 -g %s --format ZZZ f.vcf" % config_file2.name)
@@ -311,6 +316,16 @@
             output = out.getvalue().strip()
             self.assertEqual(output, expected_output)
 
+    def testIgnoreHelpArgs(self):
+        p = self.initParser()
+        self.add_arg('--arg1')
+        args, _ = self.parse_known('--arg2 --help', ignore_help_args=True)
+        self.assertEqual(args.arg1, None)
+        self.add_arg('--arg2')
+        args, _ = self.parse_known('--arg2 3 --help', ignore_help_args=True)
+        self.assertEqual(args.arg2, "3")
+        self.assertRaisesRegex(TypeError, "exit", self.parse_known, '--arg2 3 
--help', ignore_help_args=False)
+
     def testPositionalAndConfigVarLists(self):
         self.initParser()
         self.add_arg("a")
@@ -321,7 +336,6 @@
         self.assertEqual(ns.arg, ['Shell', 'someword', 'anotherword'])
         self.assertEqual(ns.a, "positional_value")
 
-
     def testMutuallyExclusiveArgs(self):
         config_file = tempfile.NamedTemporaryFile(mode="w", delete=True)
 
@@ -360,9 +374,8 @@
 
         self.assertRegex(self.format_help(),
             r'usage: .* \[-h\] --genome GENOME \[-v\]\s+ \(-f1 TYPE1_CFG_FILE 
\|'
-            ' \\s*-f2 TYPE2_CFG_FILE\\)\\s+\\(-f FRMT \\| -b\\)\n\n' +
-            7*r'.+\s+'+  # repeated 7 times because .+ matches atmost 1 line
-            'optional arguments:\n'
+            ' \\s*-f2 TYPE2_CFG_FILE\\)\\s+\\(-f FRMT \\| -b\\)\n\n'
+            '%s:\n'
             '  -h, --help            show this help message and exit\n'
             '  -f1 TYPE1_CFG_FILE, --type1-cfg-file TYPE1_CFG_FILE\n'
             '  -f2 TYPE2_CFG_FILE, --type2-cfg-file TYPE2_CFG_FILE\n'
@@ -370,7 +383,8 @@
             '  -b, --bam\\s+\\[env var: BAM_FORMAT\\]\n\n'
             'group1:\n'
             '  --genome GENOME       Path to genome file\n'
-            '  -v\n')
+            '  -v\n\n'%OPTIONAL_ARGS_STRING +
+            5*r'(.+\s*)')
         config_file.close()
 
     def testSubParsers(self):
@@ -486,6 +500,7 @@
         self.assertParseArgsRaises("argument -x is required"
                                    if sys.version_info.major < 3 else
                                    "the following arguments are required: -x, 
--y",
+                                   args="",
                                    config_file_contents="-x 3")
         self.assertParseArgsRaises("invalid float value: 'abc'",
                                    args="-x 5",
@@ -511,6 +526,46 @@
             env_vars={"bla": "2"})
         self.assertEqual(set(args), {"--bla=3", "-x", "1"})
 
+
+    def testQuotedArgumentValues(self):
+        self.initParser()
+        self.add_arg("-a")
+        self.add_arg("--b")
+        self.add_arg("-c")
+        self.add_arg("--d")
+        self.add_arg("-e")
+        self.add_arg("-q")
+        self.add_arg("--quotes")
+
+        # sys.argv equivalent of -a="1"  --b "1" -c= --d "" -e=: -q "\"'" 
--quotes "\"'"
+        ns = self.parse(args=['-a=1', '--b', '1', '-c=', '--d', '', '-e=:',
+                '-q', '"\'', '--quotes', '"\''],
+                env_vars={}, config_file_contents="")
+
+        self.assertEqual(ns.a, "1")
+        self.assertEqual(ns.b, "1")
+        self.assertEqual(ns.c, "")
+        self.assertEqual(ns.d, "")
+        self.assertEqual(ns.e, ":")
+        self.assertEqual(ns.q, '"\'')
+        self.assertEqual(ns.quotes, '"\'')
+
+    def testQuotedConfigFileValues(self):
+        self.initParser()
+        self.add_arg("--a")
+        self.add_arg("--b")
+        self.add_arg("--c")
+
+        ns = self.parse(args="", env_vars={}, config_file_contents="""
+        a="1"
+        b=:
+        c=
+        """)
+
+        self.assertEqual(ns.a, "1")
+        self.assertEqual(ns.b, ":")
+        self.assertEqual(ns.c, "")
+
     def testBooleanValuesCanBeExpressedAsNumbers(self):
         self.initParser()
         store_true_env_var_name = "STORE_TRUE"
@@ -563,6 +618,7 @@
         self.add_arg("-v", "--verbose", env_var="VERBOSE", action="store_true")
         self.assertParseArgsRaises("Unexpected value for VERBOSE: 'bla'. "
                                    "Expecting 'true', 'false', 'yes', 'no', 
'1' or '0'",
+            args="",
             env_vars={"VERBOSE" : "bla"})
         ns = self.parse("",
                         config_file_contents="verbose=true",
@@ -703,6 +759,28 @@
         self.assertEqual(ns.arg, ['Shell', 'someword', 'anotherword'])
         self.assertEqual(ns.a, "positional_value")
 
+    def testCounterCommandLine(self):
+        self.initParser()
+        self.add_arg("--verbose", "-v", action="count", default=0)
+
+        ns = self.parse(args="-v -v -v", env_vars={})
+        self.assertEqual(ns.verbose, 3)
+
+        ns = self.parse(args="-vvv", env_vars={})
+        self.assertEqual(ns.verbose, 3)
+
+    def testCounterConfigFile(self):
+        self.initParser()
+        self.add_arg("--verbose", "-v", action="count", default=0)
+
+        ns = self.parse(args="", env_vars={}, config_file_contents="""
+        verbose""")
+        self.assertEqual(ns.verbose, 1)
+
+        ns = self.parse(args="", env_vars={}, config_file_contents="""
+        verbose=3""")
+        self.assertEqual(ns.verbose, 3)
+
 class TestMisc(TestCase):
     # TODO test different action types with config file, env var
 
@@ -770,7 +848,8 @@
         self.add_arg('--genome', help='Path to genome file', required=True)
         self.assertParseArgsRaises("argument -c/--config is required"
                                    if sys.version_info.major < 3 else
-                                   "arguments are required: -c/--config",)
+                                   "arguments are required: -c/--config",
+                                   args="")
 
         temp_cfg2 = tempfile.NamedTemporaryFile(mode="w", delete=True)
         ns = self.parse("-c " + temp_cfg2.name)
@@ -783,15 +862,17 @@
         self.assertEqual(ns.genome, "hg20")
 
         self.assertRegex(self.format_help(),
-            'usage: .* \\[-h\\] -c CONFIG_FILE --genome GENOME\n\n'+
-            7*r'.+\s+'+  # repeated 7 times because .+ matches atmost 1 line
-            'optional arguments:\n'
+            'usage: .* \\[-h\\] -c CONFIG_FILE --genome GENOME\n\n'
+            '%s:\n'
             '  -h, --help\\s+ show this help message and exit\n'
             '  -c CONFIG_FILE, --config CONFIG_FILE\\s+ my config file\n'
-            '  --genome GENOME\\s+ Path to genome file\n')
+            '  --genome GENOME\\s+ Path to genome 
file\n\n'%OPTIONAL_ARGS_STRING +
+            5*r'(.+\s*)')
 
         # just run print_values() to make sure it completes and returns None
-        self.assertIsNone(self.parser.print_values(file=sys.stderr))
+        output = StringIO()
+        self.assertIsNone(self.parser.print_values(file=output))
+        self.assertIn("Command Line Args:", output.getvalue())
 
         # test ignore_unknown_config_file_keys=False
         self.initParser(ignore_unknown_config_file_keys=False)
@@ -842,21 +923,21 @@
         self.assertRegex(self.format_help(),
             r'usage: .* \[-h\] -c CONFIG_FILE\s+'
             r'\[-w CONFIG_OUTPUT_PATH\]\s* --arg1\s+ARG1\s*\[--flag\]\s*'
-            'Args that start with \'--\' \\(eg. --arg1\\) can also be set in a 
'
-            r'config file\s*\(~/.myconfig or specified via -c\).\s*'
-            r'Config file syntax allows: key=value,\s*flag=true, 
stuff=\[a,b,c\] '
-            r'\(for details, see syntax at https://goo.gl/R74nmi\).\s*'
-            r'If an arg is specified in more than\s*one place, then '
-            r'commandline values\s*override config file values which 
override\s*'
-            r'defaults.\s*'
-            r'optional arguments:\s*'
+            '%s:\\s*'
             '-h, --help \\s* show this help message and exit\n\\s*'
             r'-c CONFIG_FILE, --config CONFIG_FILE\s+my config file\s*'
             r'-w CONFIG_OUTPUT_PATH, --write-config 
CONFIG_OUTPUT_PATH\s*takes\s*'
             r'the current command line args and writes them\s*'
             r'out to a config file at the given path, then exits\s*'
             r'--arg1 ARG1\s*Arg1 help text\s*'
-            r'--flag \s*Flag help text'
+            r'--flag \s*Flag help text\s*'
+            'Args that start with \'--\' \\(eg. --arg1\\) can also be set in a 
'
+            r'config file\s*\(~/.myconfig or specified via -c\).\s*'
+            r'Config file syntax allows: key=value,\s*flag=true, 
stuff=\[a,b,c\] '
+            r'\(for details, see syntax at https://goo.gl/R74nmi\).\s*'
+            r'If an arg is specified in more than\s*one place, then '
+            r'commandline values\s*override config file values which 
override\s*'
+            r'defaults.'%OPTIONAL_ARGS_STRING
         )
 
     def test_FormatHelpProg(self):
@@ -918,6 +999,7 @@
             expected_config_file_contents.strip())
         self.assertRaisesRegex(ValueError, "Couldn't open / for writing:",
             self.parse, args = command_line_args + " -w /")
+        cfg_f.close()
 
     def testConstructor_WriteOutConfigFileArgs2(self):
         # Test constructor args:
@@ -962,6 +1044,7 @@
                          expected_config_file_contents.strip())
         self.assertRaisesRegex(ValueError, "Couldn't open / for writing:",
                                 self.parse, args = command_line_args + " -w /")
+        cfg_f.close()
 
     def testConstructor_WriteOutConfigFileArgsLong(self):
         """Test config writing with long version of arg
@@ -1005,6 +1088,7 @@
             expected_config_file_contents.strip())
         self.assertRaisesRegex(ValueError, "Couldn't open / for writing:",
             self.parse, args = command_line_args + " --write-config /")
+        cfg_f.close()
 
     def testMethodAliases(self):
         p = self.parser
@@ -1102,6 +1186,249 @@
         self.assertListEqual(parsed_obj['_list_arg1'], ['a', 'b', 'c'])
         self.assertListEqual(parsed_obj['_list_arg2'], [1, 2, 3])
 
+    def testDefaultConfigFileParser_BasicValues(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key = value # comment # comment',   'expected': ('key', 
'value', 'comment # comment')},
+            {'line': 'key=value#comment ',                'expected': ('key', 
'value#comment', None)},
+            {'line': 'key=value',                         'expected': ('key', 
'value', None)},
+            {'line': 'key =value',                        'expected': ('key', 
'value', None)},
+            {'line': 'key= value',                        'expected': ('key', 
'value', None)},
+            {'line': 'key = value',                       'expected': ('key', 
'value', None)},
+            {'line': 'key  =  value',                     'expected': ('key', 
'value', None)},
+            {'line': ' key  =  value ',                   'expected': ('key', 
'value', None)},
+            {'line': 'key:value',                         'expected': ('key', 
'value', None)},
+            {'line': 'key :value',                        'expected': ('key', 
'value', None)},
+            {'line': 'key: value',                        'expected': ('key', 
'value', None)},
+            {'line': 'key : value',                       'expected': ('key', 
'value', None)},
+            {'line': 'key  :  value',                     'expected': ('key', 
'value', None)},
+            {'line': ' key  :  value ',                   'expected': ('key', 
'value', None)},
+            {'line': 'key value',                         'expected': ('key', 
'value', None)},
+            {'line': 'key  value',                        'expected': ('key', 
'value', None)},
+            {'line': ' key    value ',                    'expected': ('key', 
'value', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_QuotedValues(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key="value"',                       'expected': ('key', 
'value', None)},
+            {'line': 'key  =  "value"',                   'expected': ('key', 
'value', None)},
+            {'line': ' key  =  "value" ',                 'expected': ('key', 
'value', None)},
+            {'line': 'key=" value "',                     'expected': ('key', 
' value ', None)},
+            {'line': 'key  =  " value "',                 'expected': ('key', 
' value ', None)},
+            {'line': ' key  =  " value " ',               'expected': ('key', 
' value ', None)},
+            {'line': "key='value'",                       'expected': ('key', 
'value', None)},
+            {'line': "key  =  'value'",                   'expected': ('key', 
'value', None)},
+            {'line': " key  =  'value' ",                 'expected': ('key', 
'value', None)},
+            {'line': "key=' value '",                     'expected': ('key', 
' value ', None)},
+            {'line': "key  =  ' value '",                 'expected': ('key', 
' value ', None)},
+            {'line': " key  =  ' value ' ",               'expected': ('key', 
' value ', None)},
+            {'line': 'key="',                             'expected': ('key', 
'"', None)},
+            {'line': 'key  =  "',                         'expected': ('key', 
'"', None)},
+            {'line': ' key  =  " ',                       'expected': ('key', 
'"', None)},
+            {'line': 'key = \'"value"\'',                 'expected': ('key', 
'"value"', None)},
+            {'line': 'key = "\'value\'"',                 'expected': ('key', 
"'value'", None)},
+            {'line': 'key = ""value""',                   'expected': ('key', 
'"value"', None)},
+            {'line': 'key = \'\'value\'\'',               'expected': ('key', 
"'value'", None)},
+            {'line': 'key="value',                        'expected': ('key', 
'"value', None)},
+            {'line': 'key  =  "value',                    'expected': ('key', 
'"value', None)},
+            {'line': ' key  =  "value ',                  'expected': ('key', 
'"value', None)},
+            {'line': 'key=value"',                        'expected': ('key', 
'value"', None)},
+            {'line': 'key  =  value"',                    'expected': ('key', 
'value"', None)},
+            {'line': ' key  =  value " ',                 'expected': ('key', 
'value "', None)},
+            {'line': "key='value",                        'expected': ('key', 
"'value", None)},
+            {'line': "key  =  'value",                    'expected': ('key', 
"'value", None)},
+            {'line': " key  =  'value ",                  'expected': ('key', 
"'value", None)},
+            {'line': "key=value'",                        'expected': ('key', 
"value'", None)},
+            {'line': "key  =  value'",                    'expected': ('key', 
"value'", None)},
+            {'line': " key  =  value ' ",                 'expected': ('key', 
"value '", None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_BlankValues(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key=',                              'expected': ('key', 
'', None)},
+            {'line': 'key =',                             'expected': ('key', 
'', None)},
+            {'line': 'key= ',                             'expected': ('key', 
'', None)},
+            {'line': 'key = ',                            'expected': ('key', 
'', None)},
+            {'line': 'key  =  ',                          'expected': ('key', 
'', None)},
+            {'line': ' key  =   ',                        'expected': ('key', 
'', None)},
+            {'line': 'key:',                              'expected': ('key', 
'', None)},
+            {'line': 'key :',                             'expected': ('key', 
'', None)},
+            {'line': 'key: ',                             'expected': ('key', 
'', None)},
+            {'line': 'key : ',                            'expected': ('key', 
'', None)},
+            {'line': 'key  :  ',                          'expected': ('key', 
'', None)},
+            {'line': ' key  :   ',                        'expected': ('key', 
'', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_UnspecifiedValues(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key ',                              'expected': ('key', 
'true', None)},
+            {'line': 'key',                               'expected': ('key', 
'true', None)},
+            {'line': 'key  ',                             'expected': ('key', 
'true', None)},
+            {'line': ' key     ',                         'expected': ('key', 
'true', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_ColonEqualSignValue(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key=:',                             'expected': ('key', 
':', None)},
+            {'line': 'key =:',                            'expected': ('key', 
':', None)},
+            {'line': 'key= :',                            'expected': ('key', 
':', None)},
+            {'line': 'key = :',                           'expected': ('key', 
':', None)},
+            {'line': 'key  =  :',                         'expected': ('key', 
':', None)},
+            {'line': ' key  =  : ',                       'expected': ('key', 
':', None)},
+            {'line': 'key:=',                             'expected': ('key', 
'=', None)},
+            {'line': 'key :=',                            'expected': ('key', 
'=', None)},
+            {'line': 'key: =',                            'expected': ('key', 
'=', None)},
+            {'line': 'key : =',                           'expected': ('key', 
'=', None)},
+            {'line': 'key  :  =',                         'expected': ('key', 
'=', None)},
+            {'line': ' key  :  = ',                       'expected': ('key', 
'=', None)},
+            {'line': 'key==',                             'expected': ('key', 
'=', None)},
+            {'line': 'key ==',                            'expected': ('key', 
'=', None)},
+            {'line': 'key= =',                            'expected': ('key', 
'=', None)},
+            {'line': 'key = =',                           'expected': ('key', 
'=', None)},
+            {'line': 'key  =  =',                         'expected': ('key', 
'=', None)},
+            {'line': ' key  =  = ',                       'expected': ('key', 
'=', None)},
+            {'line': 'key::',                             'expected': ('key', 
':', None)},
+            {'line': 'key ::',                            'expected': ('key', 
':', None)},
+            {'line': 'key: :',                            'expected': ('key', 
':', None)},
+            {'line': 'key : :',                           'expected': ('key', 
':', None)},
+            {'line': 'key  :  :',                         'expected': ('key', 
':', None)},
+            {'line': ' key  :  : ',                       'expected': ('key', 
':', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_ValuesWithComments(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key=value#comment ',                'expected': ('key', 
'value#comment', None)},
+            {'line': 'key=value #comment',                'expected': ('key', 
'value', 'comment')},
+            {'line': ' key  =  value  #  comment',        'expected': ('key', 
'value', 'comment')},
+            {'line': 'key:value#comment',                 'expected': ('key', 
'value#comment', None)},
+            {'line': 'key:value #comment',                'expected': ('key', 
'value', 'comment')},
+            {'line': ' key  :  value  #  comment',        'expected': ('key', 
'value', 'comment')},
+            {'line': 'key=value;comment ',                'expected': ('key', 
'value;comment', None)},
+            {'line': 'key=value ;comment',                'expected': ('key', 
'value', 'comment')},
+            {'line': ' key  =  value  ;  comment',        'expected': ('key', 
'value', 'comment')},
+            {'line': 'key:value;comment',                 'expected': ('key', 
'value;comment', None)},
+            {'line': 'key:value ;comment',                'expected': ('key', 
'value', 'comment')},
+            {'line': ' key  :  value  ;  comment',        'expected': ('key', 
'value', 'comment')},
+            {'line': 'key = value # comment # comment',   'expected': ('key', 
'value', 'comment # comment')},
+            {'line': 'key = "value # comment" # comment', 'expected': ('key', 
'value # comment', 'comment')},
+            {'line': 'key = "#" ; comment',               'expected': ('key', 
'#', 'comment')},
+            {'line': 'key = ";" # comment',               'expected': ('key', 
';', 'comment')},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_NegativeValues(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key = -10',                       'expected': ('key', 
'-10', None)},
+            {'line': 'key : -10',                       'expected': ('key', 
'-10', None)},
+            {'line': 'key -10',                         'expected': ('key', 
'-10', None)},
+            {'line': 'key = "-10"',                     'expected': ('key', 
'-10', None)},
+            {'line': "key  =  '-10'",                   'expected': ('key', 
'-10', None)},
+            {'line': 'key=-10',                         'expected': ('key', 
'-10', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
+    def testDefaultConfigFileParser_KeySyntax(self):
+        p = configargparse.DefaultConfigFileParser()
+
+        # test the all syntax case
+        config_lines = [
+            {'line': 'key_underscore = value',            'expected': 
('key_underscore', 'value', None)},
+            {'line': 'key_underscore=',                   'expected': 
('key_underscore', '', None)},
+            {'line': 'key_underscore',                    'expected': 
('key_underscore', 'true', None)},
+            {'line': '_key_underscore = value',           'expected': 
('_key_underscore', 'value', None)},
+            {'line': '_key_underscore=',                  'expected': 
('_key_underscore', '', None)},
+            {'line': '_key_underscore',                   'expected': 
('_key_underscore', 'true', None)},
+            {'line': 'key_underscore_ = value',           'expected': 
('key_underscore_', 'value', None)},
+            {'line': 'key_underscore_=',                  'expected': 
('key_underscore_', '', None)},
+            {'line': 'key_underscore_',                   'expected': 
('key_underscore_', 'true', None)},
+            {'line': 'key-dash = value',                  'expected': 
('key-dash', 'value', None)},
+            {'line': 'key-dash=',                         'expected': 
('key-dash', '', None)},
+            {'line': 'key-dash',                          'expected': 
('key-dash', 'true', None)},
+            {'line': 'key@word = value',                  'expected': 
('key@word', 'value', None)},
+            {'line': 'key@word=',                         'expected': 
('key@word', '', None)},
+            {'line': 'key@word',                          'expected': 
('key@word', 'true', None)},
+            {'line': 'key$word = value',                  'expected': 
('key$word', 'value', None)},
+            {'line': 'key$word=',                         'expected': 
('key$word', '', None)},
+            {'line': 'key$word',                          'expected': 
('key$word', 'true', None)},
+            {'line': 'key.word = value',                  'expected': 
('key.word', 'value', None)},
+            {'line': 'key.word=',                         'expected': 
('key.word', '', None)},
+            {'line': 'key.word',                          'expected': 
('key.word', 'true', None)},
+        ]
+
+        for test in config_lines:
+            parsed_obj = p.parse(StringIO(test['line']))
+            parsed_obj = dict(parsed_obj)
+            expected = {test['expected'][0]: test['expected'][1]}
+            self.assertDictEqual(parsed_obj, expected,
+                    msg="Line %r" % (test['line']))
+
     def testYAMLConfigFileParser_Basic(self):
         try:
             import yaml
@@ -1171,7 +1498,14 @@
 else:
     test_argparse_source_code = inspect.getsource(test.test_argparse)
     test_argparse_source_code = test_argparse_source_code.replace(
-        'argparse.ArgumentParser', 'configargparse.ArgumentParser')
+        'argparse.ArgumentParser', 'configargparse.ArgumentParser').replace(
+        'TestHelpFormattingMetaclass', '_TestHelpFormattingMetaclass').replace(
+        'test_main', '_test_main')
+
+    # pytest tries to collect tests from TestHelpFormattingMetaclass, and
+    # test_main, and raises a warning when it finds it's not a test class
+    # nor test function. Renaming TestHelpFormattingMetaclass and test_main
+    # prevents pytest from trying.
 
     # run or debug a subset of the argparse tests
     #test_argparse_source_code = test_argparse_source_code.replace(
Binary files old/ConfigArgParse-1.3/tests/test_configargparse.pyc and 
new/ConfigArgParse-1.5.1/tests/test_configargparse.pyc differ

Reply via email to