bw2 / ConfigArgParse

A drop-in replacement for argparse that allows options to also be set via config files and/or environment variables.
MIT License
719 stars 121 forks source link

Python 3.13.0b1: testBasicCase2 and testMutuallyExclusiveArgs fail because the output strings changed values #294

Open befeleme opened 2 months ago

befeleme commented 2 months ago

The help output in Python 3.13 has changed. Now, the compared strings don't match exactly, hence test failures.

_______________________ TestBasicUseCases.testBasicCase2 _______________________

self = <tests.test_configargparse.TestBasicUseCases testMethod=testBasicCase2>
use_groups = False

    def testBasicCase2(self, use_groups=False):

        ## Test command line, config file and env var values
        default_config_file = tempfile.NamedTemporaryFile(mode="w", delete=False)
        default_config_file.flush()

        p = self.initParser(default_config_files=['/etc/settings.ini',
                '/home/jeff/.user_settings', default_config_file.name])
        p.add_arg('vcf', nargs='+', help='Variant file(s)')
        if not use_groups:
            self.add_arg('--genome', help='Path to genome file', required=True)
            self.add_arg('-v', dest='verbose', action='store_true')
            self.add_arg('-g', '--my-cfg-file', required=True,
                         is_config_file=True)
            self.add_arg('-d', '--dbsnp', env_var='DBSNP_PATH')
            self.add_arg('-f', '--format',
                         choices=["BED", "MAF", "VCF", "WIG", "R"],
                         dest="fmt", metavar="FRMT", env_var="OUTPUT_FORMAT",
                         default="BED")
        else:
            g = p.add_argument_group(title="g1")
            g.add_arg('--genome', help='Path to genome file', required=True)
            g.add_arg('-v', dest='verbose', action='store_true')
            g.add_arg('-g', '--my-cfg-file', required=True,
                      is_config_file=True)
            g = p.add_argument_group(title="g2")
            g.add_arg('-d', '--dbsnp', env_var='DBSNP_PATH')
            g.add_arg('-f', '--format',
                      choices=["BED", "MAF", "VCF", "WIG", "R"],
                      dest="fmt", metavar="FRMT", env_var="OUTPUT_FORMAT",
                      default="BED")

        # make sure required args are enforced
        self.assertParseArgsRaises("too few arg"
                                   if sys.version_info.major < 3 else
                                   "the following arguments are required: vcf, -g/--my-cfg-file",
                                   args="--genome hg19")
        self.assertParseArgsRaises("Unable to open config file: file.txt. Error: No such file or director", args="-g file.txt")

        # check values after setting args on command line
        config_file2 = tempfile.NamedTemporaryFile(mode="w", delete=False)
        config_file2.flush()

        ns = self.parse(args="--genome hg19 -g %s bla.vcf " % config_file2.name)
        self.assertEqual(ns.genome, "hg19")
        self.assertEqual(ns.verbose, False)
        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'
            'Defaults:\n'
            '  --format: \\s+ BED\n')

        # check precedence: args > env > config > default using the --format arg
        default_config_file.write("--format MAF")
        default_config_file.flush()
        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')

        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')

        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'
            'Environment Variables:\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"},
            args="--genome hg19 -g %s --format WIG f.vcf" % config_file2.name)
        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'
            'Environment Variables:\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'
                'positional arguments:\n'
                '  vcf \\s+ Variant file\\(s\\)\n\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\n'%OPTIONAL_ARGS_STRING +
                7*r'(.+\s*)')
E           AssertionError: Regex didn't match: 'usage: .* \\[-h\\] --genome GENOME \\[-v\\] -g MY_CFG_FILE\n?\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\npositional arguments:\n  vcf \\s+ Variant file\\(s\\)\n\noptions:\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\n(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)' not found in "usage: pytest-3.13 [-h] --genome GENOME [-v] -g MY_CFG_FILE [-d DBSNP]\n                   [-f FRMT]\n                   vcf [vcf ...]\n\npositional arguments:\n  vcf                   Variant file(s)\n\noptions:\n  -h, --help            show this help message and exit\n  --genome GENOME       Path to genome file\n  -v\n  -g, --my-cfg-file MY_CFG_FILE\n  -d, --dbsnp DBSNP     [env var: DBSNP_PATH]\n  -f, --format FRMT     [env var: OUTPUT_FORMAT]\n\nArgs that start with '--' can also be set in a config file (/etc/settings.ini\nor /home/jeff/.user_settings or /tmp/tmpew58xqit or specified via -g). Config\nfile syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see\nsyntax at https://goo.gl/R74nmi). In general, command-line values override\nenvironment variables which override config file values which override\ndefaults.\n"

tests/test_configargparse.py:265: AssertionError
_________________ TestBasicUseCases.testBasicCase2_WithGroups __________________

self = <tests.test_configargparse.TestBasicUseCases testMethod=testBasicCase2_WithGroups>

    def testBasicCase2_WithGroups(self):
>       self.testBasicCase2(use_groups=True)

tests/test_configargparse.py:305: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_configargparse.py:279: in testBasicCase2
    self.assertRegex(self.format_help(),
E   AssertionError: Regex didn't match: 'usage: .* \\[-h\\] --genome GENOME \\[-v\\] -g MY_CFG_FILE\n?\\s+\\[-d DBSNP\\]\\s+\\[-f FRMT\\]\\s+vcf \\[vcf ...\\]\n\npositional arguments:\n  vcf \\s+ Variant file\\(s\\)\n\noptions:\n  -h, --help \\s+ show this help message and exit\n\ng1:\n  --genome GENOME \\s+ Path to genome file\n  -v\n  -g MY_CFG_FILE, --my-cfg-file MY_CFG_FILE\n\ng2:\n  -d DBSNP, --dbsnp DBSNP\\s+\\[env var: DBSNP_PATH\\]\n  -f FRMT, --format FRMT\\s+\\[env var: OUTPUT_FORMAT\\]\n\n(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)' not found in "usage: pytest-3.13 [-h] --genome GENOME [-v] -g MY_CFG_FILE [-d DBSNP]\n                   [-f FRMT]\n                   vcf [vcf ...]\n\npositional arguments:\n  vcf                   Variant file(s)\n\noptions:\n  -h, --help            show this help message and exit\n\ng1:\n  --genome GENOME       Path to genome file\n  -v\n  -g, --my-cfg-file MY_CFG_FILE\n\ng2:\n  -d, --dbsnp DBSNP     [env var: DBSNP_PATH]\n  -f, --format FRMT     [env var: OUTPUT_FORMAT]\n\nArgs that start with '--' can also be set in a config file (/etc/settings.ini\nor /home/jeff/.user_settings or /tmp/tmpaaw7d7xa or specified via -g). Config\nfile syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see\nsyntax at https://goo.gl/R74nmi). In general, command-line values override\nenvironment variables which override config file values which override\ndefaults.\n"
_________________ TestBasicUseCases.testMutuallyExclusiveArgs __________________

self = <tests.test_configargparse.TestBasicUseCases testMethod=testMutuallyExclusiveArgs>

    def testMutuallyExclusiveArgs(self):
        config_file = tempfile.NamedTemporaryFile(mode="w", delete=False)

        p = self.parser
        g = p.add_argument_group(title="group1")
        g.add_arg('--genome', help='Path to genome file', required=True)
        g.add_arg('-v', dest='verbose', action='store_true')

        g = p.add_mutually_exclusive_group(required=True)
        g.add_arg('-f1', '--type1-cfg-file', is_config_file=True)
        g.add_arg('-f2', '--type2-cfg-file', is_config_file=True)

        g = p.add_mutually_exclusive_group(required=True)
        g.add_arg('-f', '--format', choices=["BED", "MAF", "VCF", "WIG", "R"],
                     dest="fmt", metavar="FRMT", env_var="OUTPUT_FORMAT",
                     default="BED")
        g.add_arg('-b', '--bam', dest='fmt', action="store_const", const="BAM",
                  env_var='BAM_FORMAT')

        ns = self.parse(args="--genome hg19 -f1 %s --bam" % config_file.name)
        self.assertEqual(ns.genome, "hg19")
        self.assertEqual(ns.verbose, False)
        self.assertEqual(ns.fmt, "BAM")

        ns = self.parse(env_vars={"BAM_FORMAT" : "true"},
                        args="--genome hg19 -f1 %s" % config_file.name)
        self.assertEqual(ns.genome, "hg19")
        self.assertEqual(ns.verbose, False)
        self.assertEqual(ns.fmt, "BAM")
        self.assertRegex(self.format_values(),
            'Command Line Args:   --genome hg19 -f1 [^\\s]+\n'
            'Environment Variables:\n'
            '  BAM_FORMAT: \\s+ true\n'
            'Defaults:\n'
            '  --format: \\s+ BED\n')

>       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'
            '%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'
            '  -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\n'%OPTIONAL_ARGS_STRING +
            5*r'(.+\s*)')
E       AssertionError: Regex didn't match: 'usage: .* \\[-h\\] --genome GENOME \\[-v\\]\\s+ \\(-f1 TYPE1_CFG_FILE \\| \\s*-f2 TYPE2_CFG_FILE\\)\\s+\\(-f FRMT \\| -b\\)\n\noptions:\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\ngroup1:\n  --genome GENOME       Path to genome file\n  -v\n\n(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)(.+\\s*)' not found in "usage: pytest-3.13 [-h] --genome GENOME [-v]\n                   (-f1 TYPE1_CFG_FILE | -f2 TYPE2_CFG_FILE) (-f FRMT | -b)\n\noptions:\n  -h, --help            show this help message and exit\n  -f1, --type1-cfg-file TYPE1_CFG_FILE\n  -f2, --type2-cfg-file TYPE2_CFG_FILE\n  -f, --format FRMT     [env var: OUTPUT_FORMAT]\n  -b, --bam             [env var: BAM_FORMAT]\n\ngroup1:\n  --genome GENOME       Path to genome file\n  -v\n\nArgs that start with '--' can also be set in a config file (specified via -f1\nor -f2). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for\ndetails, see syntax at https://goo.gl/R74nmi). In general, command-line values\noverride environment variables which override config file values which\noverride defaults.\n"

tests/test_configargparse.py:385: AssertionError
FAILED tests/test_configargparse.py::TestBasicUseCases::testBasicCase2 - Asse...
FAILED tests/test_configargparse.py::TestBasicUseCases::testBasicCase2_WithGroups
FAILED tests/test_configargparse.py::TestBasicUseCases::testMutuallyExclusiveArgs
============ 3 failed, 32 passed, 15 deselected, 1 warning in 0.18s ============