[Piglit] [PATCH v2 6/7] Replaces getopt with argparse
Jordan Justen
jljusten at gmail.com
Fri Mar 8 09:06:20 PST 2013
On Tue, Mar 5, 2013 at 4:47 PM, Dylan Baker <baker.dylan.c at gmail.com> wrote:
> This change gets us cleaner, more readable argument parsing code.
> Another advantage of this approach is that it automatically generates
> help menus, which means options will not be implemented without a help
> entry (like --resume)
>
> V2: - Does not remove deprecated options, only marks them as deprecated
>
> Signed-off-by: Dylan Baker <baker.dylan.c at gmail.com>
> ---
> piglit-print-commands.py | 98 +++++++------------
> piglit-run.py | 249 +++++++++++++++++++++++------------------------
> 2 files changed, 159 insertions(+), 188 deletions(-)
>
> diff --git a/piglit-print-commands.py b/piglit-print-commands.py
> index 3479ef1..9dd2290 100755
> --- a/piglit-print-commands.py
> +++ b/piglit-print-commands.py
> @@ -22,7 +22,7 @@
> # DEALINGS IN THE SOFTWARE.
>
>
> -from getopt import getopt, GetoptError
> +import argparse
> import os.path as path
> import re
> import sys, os
> @@ -38,77 +38,51 @@ from framework.gleantest import GleanTest
> #############################################################################
> ##### Main program
> #############################################################################
> -def usage():
> - USAGE = """\
> -Usage: %(progName)s [options] [profile.tests]
> -
> -Prints a list of all the tests and how to run them. Ex:
> - piglit test name ::: /path/to/piglit/bin/program <args>
> - glean test name ::: PIGLIT_TEST='...' /path/to/piglit/bin/glean -v -v -v ...
> -
> -Options:
> - -h, --help Show this message
> - -t regexp, --include-tests=regexp Run only matching tests (can be used more
> - than once)
> - --tests=regexp Run only matching tests (can be used more
> - than once) DEPRICATED use --include-tests instead
> - -x regexp, --exclude-tests=regexp Exclude matching tests (can be used
> - more than once)
> -Example:
> - %(progName)s tests/all.tests
> - %(progName)s -t basic tests/all.tests
> - Print tests whose path contains the word 'basic'
> -
> - %(progName)s -t ^glean/ -t tex tests/all.tests
> - Print tests that are in the 'glean' group or whose path contains
> - the substring 'tex'
> -"""
> - print USAGE % {'progName': sys.argv[0]}
> - sys.exit(1)
>
> def main():
> - env = core.Environment()
> + parser = argparse.ArgumentParser(sys.argv)
> +
> + parser.add_argument("-t", "--include-tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Run only matching tests (can be used more than once)")
> + parser.add_argument("--tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Run only matching tests (can be used more than once)" \
> + "Deprecated")
> + parser.add_argument("-x", "--exclude-tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Exclude matching tests (can be used more than once)")
> + parser.add_argument("testProfile",
> + metavar = "<Path to testfile>",
> + help = "Path to results folder")
> +
> + args = parser.parse_args()
>
> - try:
> - option_list = [
> - "help",
> - "tests=",
> - "include-tests=",
> - "exclude-tests=",
> - ]
> - options, args = getopt(sys.argv[1:], "ht:x:", option_list)
> - except GetoptError:
> - usage()
> -
> - OptionName = ''
> - test_filter = []
> - exclude_filter = []
> -
> - for name, value in options:
> - if name in ('-h', '--help'):
> - usage()
> - elif name in ('-t', '--include-tests'):
> - test_filter.append(value)
> - env.filter.append(re.compile(value))
> - elif name in ('--tests'):
> - test_filter.append(value)
> - env.filter.append(re.compile(value))
> - print "Warning: Option --tets is deprecated, " \
> - "use --include-tests instead"
> - elif name in ('-x', '--exclude-tests'):
> - exclude_filter.append(value)
> - env.exclude_filter.append(re.compile(value))
> + env = core.Environment()
>
> - if len(args) != 1:
> - usage()
> + # If --tests is called warn that it is deprecated
> + if args.tests is no []:
> + print "Warning: Option --tests is deprecated. Use --include-tests"
>
> - profileFilename = args[0]
> + # Append includes and excludes to env
> + for each in args.include_tests:
> + env.filter.append(re.compile(each))
> + for each in args.tests:
> + env.filter.append(re.compile(each))
> + for each in args.exclude_tests:
> + env.exclude_filter.append(re.compile(each))
>
> # Change to the piglit's path
> piglit_dir = path.dirname(path.realpath(sys.argv[0]))
> os.chdir(piglit_dir)
>
> - profile = core.loadTestProfile(profileFilename)
> + profile = core.loadTestProfile(args.testFile)
>
> def getCommand(test):
> command = ''
> diff --git a/piglit-run.py b/piglit-run.py
> index 599981d..1a50651 100755
> --- a/piglit-run.py
> +++ b/piglit-run.py
> @@ -22,7 +22,7 @@
> # DEALINGS IN THE SOFTWARE.
>
>
> -from getopt import getopt, GetoptError
> +import argparse
> import os.path as path
> import re
> import sys, os
> @@ -37,123 +37,112 @@ from framework.threads import synchronized_self
> #############################################################################
> ##### Main program
> #############################################################################
> -def usage():
> - USAGE = """\
> -Usage: %(progName)s [options] [profile.tests] [results]
> - %(progName)s [options] -r [results]
> -
> -Options:
> - -h, --help Show this message
> - -d, --dry-run Do not execute the tests
> - -t regexp, --include-tests=regexp Run only matching tests (can be used more
> - than once)
> - --tests=regexp Run only matching tests (can be used more
> - than once) DEPRICATED: use --include-tests instead
> - -x regexp, --exclude-tests=regexp Excludey matching tests (can be used
> - more than once)
> - -n name, --name=name Name of the testrun
> - -c bool, --concurrent= Enable/disable concurrent test runs. Valid
> - option values are: 0, 1, on, off. (default: on)
> - DEPRICATED: use --no-concurrency to turn
> - concurrent test runs off
> - --no-concurrency Disables concurrent test runs
> - --valgrind Run tests in valgrind's memcheck.
> - -p platform, --platform=platform Name of the piglit platform to use.
> - --resume Resume and interupted test run
> -
> -Example:
> - %(progName)s tests/all.tests results/all
> - Run all tests, store the results in the directory results/all
> -
> - %(progName)s -t basic tests/all.tests results/all
> - Run all tests whose path contains the word 'basic'
> -
> - %(progName)s -t ^glean/ -t tex tests/all.tests results/all
> - Run all tests that are in the 'glean' group or whose path contains
> - the substring 'tex'
> -
> - %(progName)s -r -x bad-test results/all
> - Resume an interrupted test run whose results are stored in the
> - directory results/all, skipping bad-test.
> -"""
> - print USAGE % {'progName': sys.argv[0]}
> - sys.exit(1)
>
> def main():
> env = core.Environment()
>
> - try:
> - option_list = [
> - "help",
> - "dry-run",
> - "resume",
> - "valgrind",
> - "include-tests=",
> - "tests=",
> - "name=",
> - "exclude-tests=",
> - "no-concurrency",
> - "concurrent=",
> - "platform=",
> - ]
> - options, args = getopt(sys.argv[1:], "hdrt:n:x:c:p:", option_list)
> - except GetoptError:
> - usage()
> -
> - OptionName = ''
> - OptionResume = False
> - test_filter = []
> - exclude_filter = []
> - platform = None
> -
> - for name, value in options:
> - if name in ('-h', '--help'):
> - usage()
> - elif name in ('-d', '--dry-run'):
> - env.execute = False
> - elif name in ('-r', '--resume'):
> - OptionResume = True
> - elif name in ('--valgrind'):
> - env.valgrind = True
> - elif name in ('-t', '--include-tests'):
> - test_filter.append(value)
> - env.filter.append(re.compile(value))
> - elif name in ('--tests'):
> - test_filter.append(value)
> - env.filter.append(re.compile(value))
> - print "Warning: Option --tests is deprecated, " \
> - "use --include-tests instead"
> - elif name in ('-x', '--exclude-tests'):
> - exclude_filter.append(value)
> - env.exclude_filter.append(re.compile(value))
> - elif name in ('-n', '--name'):
> - OptionName = value
> - elif name in ('--no-concurrency'):
> + parser = argparse.ArgumentParser(sys.argv)
> +
> +
> + # Either require that a name for the test is passed or that
> + # resume is requested
> + excGroup1 = parser.add_mutually_exclusive_group()
> + excGroup1.add_argument("-n", "--name",
> + metavar = "<test name>",
> + default = None,
> + help = "Name of this test run")
> + excGroup1.add_argument("-r", "--resume",
> + action = "store_true",
> + help = "Resume an interupted test run")
> +
> + parser.add_argument("-d", "--dry-run",
> + action = "store_true",
> + help = "Do not execute the tests")
> + parser.add_argument("-t", "--include-tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Run only matching tests (can be used more than once)")
> + parser.add_argument("--tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Run only matching tests (can be used more than once) " \
> + "DEPRECATED: use --include-tests instead")
> + parser.add_argument("-x", "--exclude-tests",
> + default = [],
> + action = "append",
> + metavar = "<regex>",
> + help = "Exclude matching tests (can be used more than once)")
> +
> + # The new option going forward should be --no-concurrency, but to
> + # maintain backwards compatability the --c, --concurrent option should
> + # also be maintained. This code allows only one of the two options to be
> + # supplied, or it throws an error
> + excGroup2 = parser.add_mutually_exclusive_group()
> + excGroup2.add_argument("--no-concurrency",
> + action = "store_true",
> + help = "Disable concurrent test runs")
> + excGroup2.add_argument("-c", "--concurrent",
> + action = "store",
> + metavar = "<boolean>",
> + choices = ["1", "0", "on", "off"],
> + help = "Deprecated: Turn concrrent runs on or off")
> +
> + parser.add_argument("-p", "--platform",
> + choices = ["glx", "x11_egl", "wayland", "gbm"],
> + help = "Name of windows system passed to waffle")
> + parser.add_argument("--valgrind",
> + action = "store_true",
> + help = "Run tests in valgrind's memcheck")
> + parser.add_argument("testProfile",
> + metavar = "<Path to test profile>",
> + help = "Path to testfile to run")
> + parser.add_argument("resultsPath",
> + metavar = "<Results Path>",
> + help = "Path to results folder")
> +
> + args = parser.parse_args()
> +
> +
> + # Set the platform to pass to waffle
> + if args.platform is not None:
> + os.environ['PIGLIT_PLATFORM'] = args.platform
> +
> + # Set dry-run
> + if args.dry_run is True:
> + env.execute = False
> +
> + # Set valgrind
> + if args.valgrind is True:
> + env.valgrind = True
> +
> + # Turn concurency off if requested
> + # Deprecated
> + if args.concurrent is not None:
> + if (args.concurrent == '1' or args.concurrent == 'on'):
> + env.concurrent = True
> + print "Warning: Option -c, --concurrent is deprecated, " \
> + "concurrent test runs are on by default"
> + elif (args.concurrent == '0' or args.concurrent == 'off'):
> env.concurrent = False
> - elif name in ('-c', '--concurrent'):
> - if value in ('1', 'on'):
> - env.concurrent = True
> - print "Warning: Option -c, --concurrent is deprecated, " \
> - "concurrent test runs are on by default"
> - elif value in ('0', 'off'):
> - env.concurrent = False
> - print "Warning: Option -c, --concurrent is deprecated, " \
> - "use --no-concurrency for non-concurrent test runs"
> - else:
> - usage()
> - elif name in ('-p, --platform'):
> - platform = value
> -
> - if platform is not None:
> - os.environ['PIGLIT_PLATFORM'] = platform
> -
> - if OptionResume:
> - if test_filter or OptionName:
> - print "-r is not compatible with -t or -n."
> - usage()
> - if len(args) != 1:
> - usage()
> - resultsDir = path.realpath(args[0])
> + print "Warning: Option -c, --concurrent is deprecated, " \
> + "use --no-concurrent for non-concurrent test runs"
> + # Ne need for else, since argparse restricts the arguments allowed
> +
> + # Not deprecated
> + elif args.no_concurrency is True:
> + env.concurrent = False
> +
> + # If the deprecated tests option was passed print a warning
> + if args.tests is not []:
> + print "Warning: Option --tests is deprecated, use " \
> + "--include-tests instead"
I got the warning message when using -t. I think we may want 'if
len(args.tests) > 0' instead.
Series Reviewed-by: Jordan Justen <jordan.l.justen at intel.com>
I'll commit the series with this change later today if no further
comments come in.
Thanks,
-Jordan
> +
> + # If resume is requested attempt to load the results file
> + # in the specified path
> + if args.resume is True:
> + resultsDir = path.realpath(args.resultsPath)
>
> # Load settings from the old results JSON
> old_results = core.loadTestResults(resultsDir)
> @@ -164,14 +153,21 @@ def main():
> for value in old_results.options['exclude_filter']:
> exclude_filter.append(value)
> env.exclude_filter.append(re.compile(value))
> - else:
> - if len(args) != 2:
> - usage()
>
> - profileFilename = args[0]
> - resultsDir = path.realpath(args[1])
> -
> - # Change to the piglit's path
> + # Otherwise parse additional settings from the command line
> + else:
> + profileFilename = args.testProfile
> + resultsDir = args.resultsPath
> +
> + # Set the excluded and included tests regex
> + for each in args.include_tests:
> + env.filter.append(re.compile(each))
> + for each in args.tests:
> + env.filter.append(re.compile(each))
> + for each in args.exclude_tests:
> + env.exclude_filter.append(re.compile(each))
> +
> + # Change working directory to the root of the piglit directory
> piglit_dir = path.dirname(path.realpath(sys.argv[0]))
> os.chdir(piglit_dir)
>
> @@ -180,10 +176,10 @@ def main():
> results = core.TestrunResult()
>
> # Set results.name
> - if OptionName is '':
> - results.name = path.basename(resultsDir)
> + if args.name is not None:
> + results.name = args.name
> else:
> - results.name = OptionName
> + results.name = path.basename(resultsDir)
>
> # Begin json.
> result_filepath = os.path.join(resultsDir, 'main')
> @@ -196,9 +192,9 @@ def main():
> json_writer.open_dict()
> json_writer.write_dict_item('profile', profileFilename)
> json_writer.write_dict_key('filter')
> - result_file.write(json.dumps(test_filter))
> + result_file.write(json.dumps(args.include_tests))
> json_writer.write_dict_key('exclude_filter')
> - result_file.write(json.dumps(exclude_filter))
> + result_file.write(json.dumps(args.exclude_tests))
> json_writer.close_dict()
>
> json_writer.write_dict_item('name', results.name)
> @@ -212,7 +208,7 @@ def main():
> # If resuming an interrupted test run, re-write all of the existing
> # results since we clobbered the results file. Also, exclude them
> # from being run again.
> - if OptionResume:
> + if args.resume is True:
> for (key, value) in old_results.tests.items():
> if os.path.sep != '/':
> key = key.replace(os.path.sep, '/', -1)
> @@ -236,5 +232,6 @@ def main():
> print 'Thank you for running Piglit!'
> print 'Results have been written to ' + result_filepath
>
> +
> if __name__ == "__main__":
> main()
> --
> 1.8.1.4
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
More information about the Piglit
mailing list