Hello community, here is the log from the commit of package python-configargparse for openSUSE:Factory checked in at 2019-10-24 23:03:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-configargparse (Old) and /work/SRC/openSUSE:Factory/.python-configargparse.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-configargparse" Thu Oct 24 23:03:27 2019 rev:5 rq:742147 version:0.15.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-configargparse/python-configargparse.changes 2019-09-27 14:49:25.868611441 +0200 +++ /work/SRC/openSUSE:Factory/.python-configargparse.new.2990/python-configargparse.changes 2019-10-24 23:03:31.604127527 +0200 @@ -1,0 +2,13 @@ +Wed Oct 23 13:07:43 UTC 2019 - Marketa Calabkova <mcalabk...@suse.com> + +- Update to 0.15.1 + * Drop support for EOL Python 2.6, 3.2-3.3 + * Add Python 3.6 + * sudo no longer needed + * travis: Add latest Python versions. + * Drop support for EOL Python 3.4 + * Fix DeprecationWarning: invalid escape sequence \[ +- dropped skip-test.patch + * https://github.com/bw2/ConfigArgParse/commit/6267759da55c87508394314292c6c5286220d99d + +------------------------------------------------------------------- Old: ---- ConfigArgParse-0.14.0.tar.gz skip-test.patch New: ---- ConfigArgParse-0.15.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-configargparse.spec ++++++ --- /var/tmp/diff_new_pack.QMZp21/_old 2019-10-24 23:03:32.916129059 +0200 +++ /var/tmp/diff_new_pack.QMZp21/_new 2019-10-24 23:03:32.952129101 +0200 @@ -18,14 +18,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-configargparse -Version: 0.14.0 +Version: 0.15.1 Release: 0 Summary: A drop-in replacement for argparse License: MIT Group: Development/Languages/Python URL: https://github.com/bw2/ConfigArgParse Source: https://files.pythonhosted.org/packages/source/C/ConfigArgParse/ConfigArgParse-%{version}.tar.gz -Patch0: skip-test.patch BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module mock} BuildRequires: %{python_module pytest} @@ -53,7 +52,6 @@ %prep %setup -q -n ConfigArgParse-%{version} -%patch0 -p1 %build %python_build ++++++ ConfigArgParse-0.14.0.tar.gz -> ConfigArgParse-0.15.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/ConfigArgParse.egg-info/PKG-INFO new/ConfigArgParse-0.15.1/ConfigArgParse.egg-info/PKG-INFO --- old/ConfigArgParse-0.14.0/ConfigArgParse.egg-info/PKG-INFO 2019-01-13 17:09:05.000000000 +0100 +++ new/ConfigArgParse-0.15.1/ConfigArgParse.egg-info/PKG-INFO 2019-10-08 16:50:55.000000000 +0200 @@ -1,12 +1,25 @@ Metadata-Version: 2.1 Name: ConfigArgParse -Version: 0.14.0 +Version: 0.15.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 -Author: Zorro -Author-email: zorro3.git...@gmail.com License: MIT -Description: Overview +Description: ConfigArgParse + -------------- + + .. image:: https://img.shields.io/pypi/v/ConfigArgParse.svg?style=flat + :alt: PyPI version + :target: https://pypi.python.org/pypi/ConfigArgParse + + .. image:: https://img.shields.io/pypi/pyversions/ConfigArgParse.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/ConfigArgParse + + .. image:: https://travis-ci.org/bw2/ConfigArgParse.svg?branch=master + :alt: Travis CI build + :target: https://travis-ci.org/bw2/ConfigArgParse + + Overview ~~~~~~~~ Applications with more than a handful of user-settable options are best @@ -45,7 +58,7 @@ - extensible (:code:`ConfigFileParser` can be subclassed to define a new config file format) - unittested by running the unittests that came with argparse but on - configargparse, and using tox to test with python2.7+ and python3+ + configargparse, and using tox to test with Python 2.7 and Python 3+ Example ~~~~~~~ @@ -271,7 +284,7 @@ Previously existing modules (PyPI search keywords: config argparse): - - argparse (built-in module python v2.7+ ) + - argparse (built-in module Python v2.7+) - Good: @@ -302,7 +315,7 @@ "choices" are not handled as expected. For example, if you specify a required value in a config file, you still have to specify it again on the command line. - - doesn't work with python 3 yet + - doesn't work with Python 3 yet - no unit tests, code not well documented - appsettings v0.5 (https://pypi.python.org/pypi/appsettings) @@ -317,7 +330,7 @@ - passes in config file and env settings via parse_args namespace param - - tests not finished and don't work with python3 (import + - tests not finished and don't work with Python 3 (import StringIO) - argparse_config v0.5.1 @@ -329,7 +342,7 @@ - Bad: - - doesn't work with python3 (error during pip install) + - doesn't work with Python 3 (error during pip install) - yconf v0.3.2 - (https://pypi.python.org/pypi/yconf) - features and interface not that great @@ -346,7 +359,7 @@ - Bad: - - doesn't work with python3 + - doesn't work with Python 3 - 2+ years since last release to PyPI - apparently unmaintained @@ -400,13 +413,12 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 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: yaml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/PKG-INFO new/ConfigArgParse-0.15.1/PKG-INFO --- old/ConfigArgParse-0.14.0/PKG-INFO 2019-01-13 17:09:05.000000000 +0100 +++ new/ConfigArgParse-0.15.1/PKG-INFO 2019-10-08 16:50:55.000000000 +0200 @@ -1,12 +1,25 @@ Metadata-Version: 2.1 Name: ConfigArgParse -Version: 0.14.0 +Version: 0.15.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 -Author: Zorro -Author-email: zorro3.git...@gmail.com License: MIT -Description: Overview +Description: ConfigArgParse + -------------- + + .. image:: https://img.shields.io/pypi/v/ConfigArgParse.svg?style=flat + :alt: PyPI version + :target: https://pypi.python.org/pypi/ConfigArgParse + + .. image:: https://img.shields.io/pypi/pyversions/ConfigArgParse.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/ConfigArgParse + + .. image:: https://travis-ci.org/bw2/ConfigArgParse.svg?branch=master + :alt: Travis CI build + :target: https://travis-ci.org/bw2/ConfigArgParse + + Overview ~~~~~~~~ Applications with more than a handful of user-settable options are best @@ -45,7 +58,7 @@ - extensible (:code:`ConfigFileParser` can be subclassed to define a new config file format) - unittested by running the unittests that came with argparse but on - configargparse, and using tox to test with python2.7+ and python3+ + configargparse, and using tox to test with Python 2.7 and Python 3+ Example ~~~~~~~ @@ -271,7 +284,7 @@ Previously existing modules (PyPI search keywords: config argparse): - - argparse (built-in module python v2.7+ ) + - argparse (built-in module Python v2.7+) - Good: @@ -302,7 +315,7 @@ "choices" are not handled as expected. For example, if you specify a required value in a config file, you still have to specify it again on the command line. - - doesn't work with python 3 yet + - doesn't work with Python 3 yet - no unit tests, code not well documented - appsettings v0.5 (https://pypi.python.org/pypi/appsettings) @@ -317,7 +330,7 @@ - passes in config file and env settings via parse_args namespace param - - tests not finished and don't work with python3 (import + - tests not finished and don't work with Python 3 (import StringIO) - argparse_config v0.5.1 @@ -329,7 +342,7 @@ - Bad: - - doesn't work with python3 (error during pip install) + - doesn't work with Python 3 (error during pip install) - yconf v0.3.2 - (https://pypi.python.org/pypi/yconf) - features and interface not that great @@ -346,7 +359,7 @@ - Bad: - - doesn't work with python3 + - doesn't work with Python 3 - 2+ years since last release to PyPI - apparently unmaintained @@ -400,13 +413,12 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 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: yaml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/README.rst new/ConfigArgParse-0.15.1/README.rst --- old/ConfigArgParse-0.14.0/README.rst 2018-02-04 18:57:28.000000000 +0100 +++ new/ConfigArgParse-0.15.1/README.rst 2019-10-08 16:02:52.000000000 +0200 @@ -1,3 +1,18 @@ +ConfigArgParse +-------------- + +.. image:: https://img.shields.io/pypi/v/ConfigArgParse.svg?style=flat + :alt: PyPI version + :target: https://pypi.python.org/pypi/ConfigArgParse + +.. image:: https://img.shields.io/pypi/pyversions/ConfigArgParse.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/ConfigArgParse + +.. image:: https://travis-ci.org/bw2/ConfigArgParse.svg?branch=master + :alt: Travis CI build + :target: https://travis-ci.org/bw2/ConfigArgParse + Overview ~~~~~~~~ @@ -37,7 +52,7 @@ - extensible (:code:`ConfigFileParser` can be subclassed to define a new config file format) - unittested by running the unittests that came with argparse but on - configargparse, and using tox to test with python2.7+ and python3+ + configargparse, and using tox to test with Python 2.7 and Python 3+ Example ~~~~~~~ @@ -263,7 +278,7 @@ Previously existing modules (PyPI search keywords: config argparse): -- argparse (built-in module python v2.7+ ) +- argparse (built-in module Python v2.7+) - Good: @@ -294,7 +309,7 @@ "choices" are not handled as expected. For example, if you specify a required value in a config file, you still have to specify it again on the command line. - - doesn't work with python 3 yet + - doesn't work with Python 3 yet - no unit tests, code not well documented - appsettings v0.5 (https://pypi.python.org/pypi/appsettings) @@ -309,7 +324,7 @@ - passes in config file and env settings via parse_args namespace param - - tests not finished and don't work with python3 (import + - tests not finished and don't work with Python 3 (import StringIO) - argparse_config v0.5.1 @@ -321,7 +336,7 @@ - Bad: - - doesn't work with python3 (error during pip install) + - doesn't work with Python 3 (error during pip install) - yconf v0.3.2 - (https://pypi.python.org/pypi/yconf) - features and interface not that great @@ -338,7 +353,7 @@ - Bad: - - doesn't work with python3 + - doesn't work with Python 3 - 2+ years since last release to PyPI - apparently unmaintained diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/configargparse.py new/ConfigArgParse-0.15.1/configargparse.py --- old/ConfigArgParse-0.14.0/configargparse.py 2019-01-13 16:51:44.000000000 +0100 +++ new/ConfigArgParse-0.15.1/configargparse.py 2019-10-08 16:50:17.000000000 +0200 @@ -4,17 +4,13 @@ import re import sys import types +from collections import OrderedDict if sys.version_info >= (3, 0): from io import StringIO else: from StringIO import StringIO -if sys.version_info < (2, 7): - from ordereddict import OrderedDict -else: - from collections import OrderedDict - ACTION_TYPES_THAT_DONT_NEED_A_VALUE = (argparse._StoreTrueAction, argparse._StoreFalseAction, argparse._CountAction, @@ -152,8 +148,8 @@ if not line or line[0] in ["#", ";", "["] or line.startswith("---"): continue white_space = "\\s*" - key = "(?P<key>[^:=;#\s]+?)" - value = white_space+"[:=\s]"+white_space+"(?P<value>.+?)" + 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) @@ -174,7 +170,7 @@ items[key] = value continue - raise ConfigFileParserException("Unexpected line %s in %s: %s" % (i, + raise ConfigFileParserException("Unexpected line {} in {}: {}".format(i, getattr(stream, 'name', 'stream'), line)) return items @@ -187,7 +183,7 @@ if isinstance(value, list): # handle special case of lists value = "["+", ".join(map(str, value))+"]" - r.write("%s = %s\n" % (key, value)) + r.write("{} = {}\n".format(key, value)) return r.getvalue() @@ -265,22 +261,7 @@ environment variables and .ini or .yaml-style config files. """ - def __init__(self, - add_config_file_help=True, - add_env_var_help=True, - auto_env_var_prefix=None, - default_config_files=[], - ignore_unknown_config_file_keys=False, - config_file_parser_class=DefaultConfigFileParser, - args_for_setting_config_path=[], - config_arg_is_required=False, - config_arg_help_message="config file path", - args_for_writing_out_config_file=[], - write_out_config_file_arg_help_message="takes the current command line " - "args and writes them out to a config file at the given path, then " - "exits", - **kwargs - ): + def __init__(self, *args, **kwargs): """Supports args of the argparse.ArgumentParser constructor as **kwargs, as well as the following additional args. @@ -331,11 +312,34 @@ write_out_config_file_arg_help_message: The help message to use for the args in args_for_writing_out_config_file. """ + # This is the only way to make positional args (tested in the argparse + # main test suite) and keyword arguments work across both Python 2 and + # 3. This could be refactored to not need extra local variables. + add_config_file_help = kwargs.pop('add_config_file_help', True) + add_env_var_help = kwargs.pop('add_env_var_help', True) + auto_env_var_prefix = kwargs.pop('auto_env_var_prefix', None) + default_config_files = kwargs.pop('default_config_files', []) + ignore_unknown_config_file_keys = kwargs.pop( + 'ignore_unknown_config_file_keys', False) + config_file_parser_class = kwargs.pop('config_file_parser_class', + DefaultConfigFileParser) + args_for_setting_config_path = kwargs.pop( + 'args_for_setting_config_path', []) + config_arg_is_required = kwargs.pop('config_arg_is_required', False) + config_arg_help_message = kwargs.pop('config_arg_help_message', + "config file path") + args_for_writing_out_config_file = kwargs.pop( + 'args_for_writing_out_config_file', []) + write_out_config_file_arg_help_message = kwargs.pop( + 'write_out_config_file_arg_help_message', "takes the current " + "command line args and writes them out to a config file at the " + "given path, then exits") + self._add_config_file_help = add_config_file_help self._add_env_var_help = add_env_var_help self._auto_env_var_prefix = auto_env_var_prefix - argparse.ArgumentParser.__init__(self, **kwargs) + argparse.ArgumentParser.__init__(self, *args, **kwargs) # parse the additional args if config_file_parser_class is None: @@ -394,7 +398,7 @@ args = list(args) # normalize args by converting args like --key=value to --key value - normalized_args = list() + normalized_args = [] for arg in args: if arg and arg[0] in self.prefix_chars and '=' in arg: key, value = arg.split('=', 1) @@ -431,6 +435,7 @@ # add env var settings to the commandline that aren't there already env_var_args = [] + nargs = False actions_with_env_var_values = [a for a in self._actions if not a.is_positional_arg and a.env_var and a.env_var in env_vars and not already_on_command_line(args, a.option_strings)] @@ -439,20 +444,23 @@ value = env_vars[key] # Make list-string into list. if action.nargs or isinstance(action, argparse._AppendAction): - element_capture = re.match('\[(.*)\]', value) + nargs = True + element_capture = re.match(r'\[(.*)\]', value) if element_capture: value = [val.strip() for val in element_capture.group(1).split(',') if val.strip()] env_var_args += self.convert_item_to_command_line_arg( action, key, value) - args = args + env_var_args + if nargs: + args = args + env_var_args + else: + args = env_var_args + args if env_var_args: self._source_to_settings[_ENV_VAR_SOURCE_KEY] = OrderedDict( [(a.env_var, (a, env_vars[a.env_var])) for a in actions_with_env_var_values]) - # before parsing any config files, check if -h was specified. supports_help_arg = any( a for a in self._actions if isinstance(a, argparse._HelpAction)) @@ -460,8 +468,8 @@ "-h" in args or "--help" in args) # prepare for reading config file(s) - known_config_keys = dict((config_key, action) for action in self._actions - for config_key in self.get_possible_config_keys(action)) + known_config_keys = {config_key: action for action in self._actions + for config_key in self.get_possible_config_keys(action)} # open the config file(s) config_streams = [] @@ -484,6 +492,7 @@ # add each config item to the commandline unless it's there already config_args = [] + nargs = False for key, value in config_items.items(): if key in known_config_keys: action = known_config_keys[key] @@ -503,9 +512,14 @@ if source_key not in self._source_to_settings: self._source_to_settings[source_key] = OrderedDict() self._source_to_settings[source_key][key] = (action, value) + if (action and action.nargs or + isinstance(action, argparse._AppendAction)): + nargs = True - args = args + config_args - + if nargs: + args = args + config_args + else: + args = config_args + args # save default settings for use by print_values() default_settings = OrderedDict() @@ -553,7 +567,7 @@ with open(output_file_path, "w") as output_file: pass except IOError as e: - raise ValueError("Couldn't open %s for writing: %s" % ( + raise ValueError("Couldn't open {} for writing: {}".format( output_file_path, e)) if output_file_paths: # generate the config file contents @@ -675,7 +689,7 @@ args.append( command_line_key ) args.append( value ) else: - raise ValueError("Unexpected value type %s for value: %s" % ( + raise ValueError("Unexpected value type {} for value: {}".format( type(value), value)) return args @@ -692,7 +706,7 @@ return keys for arg in action.option_strings: - if any([arg.startswith(2*c) for c in self.prefix_chars]): + if any(arg.startswith(2*c) for c in self.prefix_chars): keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla'] return keys @@ -771,7 +785,7 @@ r.write(source) for key, (action, value) in settings.items(): if key: - r.write(" %-19s%s\n" % (key+":", value)) + r.write(" {:<19}{}\n".format(key+":", value)) else: if isinstance(value, str): r.write(" %s\n" % value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/setup.py new/ConfigArgParse-0.15.1/setup.py --- old/ConfigArgParse-0.14.0/setup.py 2019-01-13 17:01:11.000000000 +0100 +++ new/ConfigArgParse-0.15.1/setup.py 2019-10-08 16:50:27.000000000 +0200 @@ -34,7 +34,7 @@ logging.debug("Can't use port %d: %s" % (port, e.strerror)) continue - print("HTML coverage report now available at http://%s%s" % ( + print("HTML coverage report now available at http://{}{}".format( socket.gethostname(), (":%s" % port) if port != 80 else "")) os.chdir(directory) @@ -72,24 +72,14 @@ tests_require = [ 'PyYAML', ] -if sys.version_info < (2, 7): - install_requires.extend([ - 'argparse', - 'ordereddict', - ]) - tests_require.extend([ - 'unittest2', - ]) setup( name='ConfigArgParse', - version="0.14.0", + version="0.15.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, - author='Zorro', - author_email='zorro3.git...@gmail.com', url='https://github.com/bw2/ConfigArgParse', py_modules=['configargparse'], include_package_data=True, @@ -102,17 +92,16 @@ 'License :: OSI Approved :: MIT License', 'Natural Language :: English', "Programming Language :: Python :: 2", - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ], test_suite='tests', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', install_requires=install_requires, tests_require=tests_require, extras_require = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ConfigArgParse-0.14.0/tests/test_configargparse.py new/ConfigArgParse-0.15.1/tests/test_configargparse.py --- old/ConfigArgParse-0.14.0/tests/test_configargparse.py 2019-01-13 16:51:44.000000000 +0100 +++ new/ConfigArgParse-0.15.1/tests/test_configargparse.py 2019-10-08 16:02:52.000000000 +0200 @@ -5,17 +5,13 @@ import sys import tempfile import types +import unittest try: import mock except ImportError: from unittest import mock -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest - if sys.version_info >= (3, 0): from io import StringIO else: @@ -80,14 +76,14 @@ # make sure required args are enforced self.assertParseArgsRaises("too few arg" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required", args="") self.assertParseArgsRaises("argument -y/--arg-y is required" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required: -y/--arg-y", args="-x --arg-z 11 file1.txt") self.assertParseArgsRaises("argument --arg-z is required" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required: --arg-z", args="file1.txt file2.txt file3.txt -x -y 1") @@ -116,11 +112,11 @@ self.assertEqual(ns.arg_z, [40]) self.assertRegex(self.format_values(), - 'Command Line Args: \s+ file1.txt file2.txt\n' - 'Config File \(method arg\):\n' - ' arg-x: \s+ True\n' - ' arg-y: \s+ 10\n' - ' arg-z: \s+ 40\n') + 'Command Line Args: \\s+ file1.txt file2.txt\n' + 'Config File \\(method arg\\):\n' + ' arg-x: \\s+ True\n' + ' arg-y: \\s+ 10\n' + ' arg-z: \\s+ 40\n') # check values after setting args in both command line and config file ns = self.parse(args="file1.txt file2.txt --arg-x -y 3 --arg-z 100 ", @@ -171,7 +167,7 @@ # make sure required args are enforced self.assertParseArgsRaises("too few arg" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required: vcf, -g/--my-cfg-file", args="--genome hg19") self.assertParseArgsRaises("not found: file.txt", args="-g file.txt") @@ -183,14 +179,14 @@ ns = self.parse(args="--genome hg19 -g %s bla.vcf " % config_file2.name) self.assertEqual(ns.genome, "hg19") self.assertEqual(ns.verbose, False) - self.assertEqual(ns.dbsnp, None) + self.assertIsNone(ns.dbsnp) self.assertEqual(ns.fmt, "BED") self.assertListEqual(ns.vcf, ["bla.vcf"]) self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -g [^\s]+ bla.vcf\n' + 'Command Line Args: --genome hg19 -g [^\\s]+ bla.vcf\n' 'Defaults:\n' - ' --format: \s+ BED\n') + ' --format: \\s+ BED\n') # check precedence: args > env > config > default using the --format arg default_config_file.write("--format MAF") @@ -198,28 +194,28 @@ ns = self.parse(args="--genome hg19 -g %s f.vcf " % config_file2.name) self.assertEqual(ns.fmt, "MAF") self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -g [^\s]+ f.vcf\n' - 'Config File \([^\s]+\):\n' - ' --format: \s+ MAF\n') + 'Command Line Args: --genome hg19 -g [^\\s]+ f.vcf\n' + 'Config File \\([^\\s]+\\):\n' + ' --format: \\s+ MAF\n') config_file2.write("--format VCF") config_file2.flush() ns = self.parse(args="--genome hg19 -g %s f.vcf " % config_file2.name) self.assertEqual(ns.fmt, "VCF") self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -g [^\s]+ f.vcf\n' - 'Config File \([^\s]+\):\n' - ' --format: \s+ VCF\n') + 'Command Line Args: --genome hg19 -g [^\\s]+ f.vcf\n' + 'Config File \\([^\\s]+\\):\n' + ' --format: \\s+ VCF\n') ns = self.parse(env_vars={"OUTPUT_FORMAT":"R", "DBSNP_PATH":"/a/b.vcf"}, args="--genome hg19 -g %s f.vcf " % config_file2.name) self.assertEqual(ns.fmt, "R") self.assertEqual(ns.dbsnp, "/a/b.vcf") self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -g [^\s]+ f.vcf\n' + 'Command Line Args: --genome hg19 -g [^\\s]+ f.vcf\n' 'Environment Variables:\n' - ' DBSNP_PATH: \s+ /a/b.vcf\n' - ' OUTPUT_FORMAT: \s+ R\n') + ' DBSNP_PATH: \\s+ /a/b.vcf\n' + ' OUTPUT_FORMAT: \\s+ R\n') ns = self.parse(env_vars={"OUTPUT_FORMAT":"R", "DBSNP_PATH":"/a/b.vcf", "ANOTHER_VAR":"something"}, @@ -227,40 +223,40 @@ self.assertEqual(ns.fmt, "WIG") self.assertEqual(ns.dbsnp, "/a/b.vcf") self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -g [^\s]+ --format WIG f.vcf\n' + 'Command Line Args: --genome hg19 -g [^\\s]+ --format WIG f.vcf\n' 'Environment Variables:\n' - ' DBSNP_PATH: \s+ /a/b.vcf\n') + ' DBSNP_PATH: \\s+ /a/b.vcf\n') 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*'(.+\s+)'+ # repeated 8 times because .+ matches atmost 1 line + '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 'positional arguments:\n' - ' vcf \s+ Variant file\(s\)\n\n' + ' vcf \\s+ Variant file\\(s\\)\n\n' 'optional arguments:\n' - ' -h, --help \s+ show this help message and exit\n' - ' --genome GENOME \s+ Path to genome file\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') + ' -d DBSNP, --dbsnp DBSNP\\s+\\[env var: DBSNP_PATH\\]\n' + ' -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n') 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*'.+\s+'+ # repeated 8 times because .+ matches atmost 1 line + '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 'positional arguments:\n' - ' vcf \s+ Variant file\(s\)\n\n' + ' vcf \\s+ Variant file\\(s\\)\n\n' 'optional arguments:\n' - ' -h, --help \s+ show this help message and exit\n\n' + ' -h, --help \\s+ show this help message and exit\n\n' 'g1:\n' - ' --genome GENOME \s+ Path to genome file\n' + ' --genome GENOME \\s+ Path to genome file\n' ' -v\n' ' -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') + ' -d DBSNP, --dbsnp DBSNP\\s+\\[env var: DBSNP_PATH\\]\n' + ' -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n') self.assertParseArgsRaises("invalid choice: 'ZZZ'", args="--genome hg19 -g %s --format ZZZ f.vcf" % config_file2.name) @@ -315,22 +311,22 @@ self.assertEqual(ns.verbose, False) self.assertEqual(ns.fmt, "BAM") self.assertRegex(self.format_values(), - 'Command Line Args: --genome hg19 -f1 [^\s]+\n' + 'Command Line Args: --genome hg19 -f1 [^\\s]+\n' 'Environment Variables:\n' - ' BAM_FORMAT: \s+ true\n' + ' BAM_FORMAT: \\s+ true\n' 'Defaults:\n' - ' --format: \s+ BED\n') + ' --format: \\s+ BED\n') self.assertRegex(self.format_help(), - 'usage: .* \[-h\] --genome GENOME \[-v\]\s+ \(-f1 TYPE1_CFG_FILE \|' - ' \s*-f2 TYPE2_CFG_FILE\)\s+\(-f FRMT \| -b\)\n\n' + - 7*'.+\s+'+ # repeated 7 times because .+ matches atmost 1 line + 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' ' -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' - ' -f FRMT, --format FRMT\s+\[env var: OUTPUT_FORMAT\]\n' - ' -b, --bam\s+\[env var: BAM_FORMAT\]\n\n' + ' -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n' + ' -b, --bam\\s+\\[env var: BAM_FORMAT\\]\n\n' 'group1:\n' ' --genome GENOME Path to genome file\n' ' -v\n') @@ -430,28 +426,28 @@ self.assertEqual(ns.x, 1) self.assertEqual(ns.y, 12.1) self.assertEqual(ns.z, 'z 1') - self.assertEqual(ns.c, None) + self.assertIsNone(ns.c) self.assertEqual(ns.b, True) self.assertEqual(ns.a, [33]) self.assertRegex(self.format_values(), - 'Command Line Args: \s+ -x 1\n' - 'Config File \(method arg\):\n' - ' y: \s+ 12.1\n' - ' b: \s+ True\n' - ' a: \s+ 33\n' - ' z: \s+ z 1\n') + 'Command Line Args: \\s+ -x 1\n' + 'Config File \\(method arg\\):\n' + ' y: \\s+ 12.1\n' + ' b: \\s+ True\n' + ' a: \\s+ 33\n' + ' z: \\s+ z 1\n') # -x is not a long arg so can't be set via config file self.assertParseArgsRaises("argument -x is required" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required: -x, --y", config_file_contents="-x 3") self.assertParseArgsRaises("invalid float value: 'abc'", args="-x 5", config_file_contents="y: abc") self.assertParseArgsRaises("argument --y is required" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "the following arguments are required: --y", args="-x 5", config_file_contents="z: 1") @@ -469,7 +465,7 @@ self.initParser(ignore_unknown_config_file_keys=False) ns, args = self.parse_known(args="-x 1", config_file_contents="bla=3", env_vars={"bla": "2"}) - self.assertEqual(set(args), set(["--bla", "3", "-x", "1"])) + self.assertEqual(set(args), {"--bla", "3", "-x", "1"}) def testBooleanValuesCanBeExpressedAsNumbers(self): self.initParser() @@ -544,7 +540,7 @@ self.initParser() self.add_arg("-f", "--file", env_var="FILES", action="append", type=int) ns = self.parse("", env_vars = {"file": "[1,2,3]", "VERBOSE": "true"}) - self.assertEqual(ns.file, None) + self.assertIsNone(ns.file) def testAutoEnvVarPrefix(self): self.initParser(auto_env_var_prefix="TEST_") @@ -561,8 +557,8 @@ "TEST2": "22", "TEST_ARG4": "arg4_value", "TEST_ARG4_MORE": "magic"}) - self.assertEqual(ns.arg0, None) - self.assertEqual(ns.arg1, None) + self.assertIsNone(ns.arg0) + self.assertIsNone(ns.arg1) self.assertEqual(ns.arg2, 22) self.assertEqual(ns.arg4, "arg4_value") self.assertEqual(ns.arg4_more, "magic") @@ -665,7 +661,7 @@ default_config_files=[temp_cfg.name]) self.add_arg('--genome', help='Path to genome file', required=True) self.assertParseArgsRaises("argument -c/--config is required" - if sys.version_info < (3,3) else + if sys.version_info.major < 3 else "arguments are required: -c/--config",) temp_cfg2 = tempfile.NamedTemporaryFile(mode="w", delete=True) @@ -679,15 +675,15 @@ self.assertEqual(ns.genome, "hg20") self.assertRegex(self.format_help(), - 'usage: .* \[-h\] -c CONFIG_FILE --genome GENOME\n\n'+ - 7*'.+\s+'+ # repeated 7 times because .+ matches atmost 1 line + 'usage: .* \\[-h\\] -c CONFIG_FILE --genome GENOME\n\n'+ + 7*r'.+\s+'+ # repeated 7 times because .+ matches atmost 1 line 'optional arguments:\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') + ' -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') # just run print_values() to make sure it completes and returns None - self.assertEqual(self.parser.print_values(file=sys.stderr), None) + self.assertIsNone(self.parser.print_values(file=sys.stderr)) # test ignore_unknown_config_file_keys=False self.initParser(ignore_unknown_config_file_keys=False) @@ -719,7 +715,7 @@ self.add_arg('--hello', type=int, required=False) - command = '-c {0} --hello 2'.format(temp_cfg.name) + command = '-c {} --hello 2'.format(temp_cfg.name) known, unknown = self.parse_known(command) @@ -736,25 +732,33 @@ self.add_arg('--flag', help='Flag help text', action="store_true") self.assertRegex(self.format_help(), - 'usage: .* \[-h\] -c CONFIG_FILE\s+' - '\[-w CONFIG_OUTPUT_PATH\]\s* --arg1 ARG1\s*\[--flag\]\s*' - 'Args that start with \'--\' \(eg. --arg1\) can also be set in a ' - 'config file\s*\(~/.myconfig or specified via -c\).\s*' - 'Config file syntax allows: key=value,\s*flag=true, stuff=\[a,b,c\] ' - '\(for details, see syntax at https://goo.gl/R74nmi\).\s*' - 'If an arg is specified in more than\s*one place, then ' - 'commandline values\s*override config file values which override\s*' - 'defaults.\s*' - 'optional arguments:\s*' - '-h, --help \s* show this help message and exit\n\s*' - '-c CONFIG_FILE, --config CONFIG_FILE\s+my config file\s*' - '-w CONFIG_OUTPUT_PATH, --write-config CONFIG_OUTPUT_PATH\s*takes\s*' - 'the current command line args and writes them\s*' - 'out to a config file at the given path, then exits\s*' - '--arg1 ARG1\s*Arg1 help text\s*' - '--flag \s*Flag help text' + r'usage: .* \[-h\] -c CONFIG_FILE\s+' + r'\[-w CONFIG_OUTPUT_PATH\]\s* --arg1 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*' + '-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' ) + def test_FormatHelpProg(self): + self.initParser('format_help_prog') + self.assertRegex(self.format_help(), 'usage: format_help_prog .*') + + def test_FormatHelpProgLib(self): + parser = argparse.ArgumentParser('format_help_prog') + self.assertRegex(parser.format_help(), 'usage: format_help_prog .*') + class CustomClass(object): def __init__(self, name): self.name = name @@ -926,7 +930,7 @@ def testDefaultConfigFileParser_Basic(self): p = configargparse.DefaultConfigFileParser() - self.assertTrue(len(p.get_syntax_description()) > 0) + self.assertGreater(len(p.get_syntax_description()), 0) # test the simplest case input_config_str = StringIO("""a: 3\n""") @@ -936,7 +940,7 @@ self.assertEqual(input_config_str.getvalue().replace(": ", " = "), output_config_str) - self.assertDictEqual(parsed_obj, dict([('a', '3')])) + self.assertDictEqual(parsed_obj, {'a': '3'}) def testDefaultConfigFileParser_All(self): p = configargparse.DefaultConfigFileParser() @@ -965,13 +969,13 @@ l.replace(': ', ' = ') for l in config_lines if l.startswith('_'))+"\n", output_config_str) - self.assertDictEqual(parsed_obj, dict([ - ('_a', '3'), - ('_b', 'c'), - ('_list_arg1', ['a', 'b', 'c']), - ('_str_arg', 'true'), - ('_list_arg2', ['1', '2', '3']), - ])) + self.assertDictEqual(parsed_obj, { + '_a': '3', + '_b': 'c', + '_list_arg1': ['a', 'b', 'c'], + '_str_arg': 'true', + '_list_arg2': ['1', '2', '3'], + }) self.assertListEqual(parsed_obj['_list_arg1'], ['a', 'b', 'c']) self.assertListEqual(parsed_obj['_list_arg2'], ['1', '2', '3']) @@ -985,7 +989,7 @@ return p = configargparse.YAMLConfigFileParser() - self.assertTrue(len(p.get_syntax_description()) > 0) + self.assertGreater(len(p.get_syntax_description()), 0) input_config_str = StringIO("""a: '3'\n""") parsed_obj = p.parse(input_config_str) @@ -993,7 +997,7 @@ self.assertEqual(input_config_str.getvalue(), output_config_str) - self.assertDictEqual(parsed_obj, dict([('a', '3')])) + self.assertDictEqual(parsed_obj, {'a': '3'}) def testYAMLConfigFileParser_All(self): try: @@ -1022,10 +1026,7 @@ output_config_str = p.serialize(parsed_obj) self.assertEqual(input_config_str.getvalue(), output_config_str) - self.assertDictEqual(parsed_obj, dict([ - ('a', '3'), - ('list_arg', [1,2,3]), - ])) + self.assertDictEqual(parsed_obj, {'a': '3', 'list_arg': [1,2,3]}) @@ -1039,17 +1040,12 @@ #Sig = test.test_argparse.Sig #NS = test.test_argparse.NS except ImportError: - if sys.version_info < (2, 7): - logging.info("\n\n" + ("=" * 30) + - "\nINFO: Skipping tests for argparse (Python < 2.7)\n" - + ("=" * 30) + "\n") - else: - logging.error("\n\n" - "============================\n" - "ERROR: Many tests couldn't be run because 'import test.test_argparse' " - "failed. Try building/installing python from source rather than through" - " a package manager.\n" - "============================\n") + logging.error("\n\n" + "============================\n" + "ERROR: Many tests couldn't be run because 'import test.test_argparse' " + "failed. Try building/installing python from source rather than through" + " a package manager.\n" + "============================\n") else: test_argparse_source_code = inspect.getsource(test.test_argparse) test_argparse_source_code = test_argparse_source_code.replace(