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