<div dir="ltr">Great job, Serhiy. In general, eating our own dogfood is a great idea. The more we use new Python features in our own stuff, the better.<br><br>Eli<br><div><div class="gmail_extra"><br><br><div class="gmail_quote">

On Thu, Aug 29, 2013 at 2:27 AM, serhiy.storchaka <span dir="ltr"><<a href="mailto:python-checkins@python.org" target="_blank">python-checkins@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<a href="http://hg.python.org/cpython/rev/997de0edc5bd" target="_blank">http://hg.python.org/cpython/rev/997de0edc5bd</a><br>
changeset:   85444:997de0edc5bd<br>
parent:      85442:676bbd5b0254<br>
user:        Serhiy Storchaka <<a href="mailto:storchaka@gmail.com">storchaka@gmail.com</a>><br>
date:        Thu Aug 29 12:26:23 2013 +0300<br>
summary:<br>
  Issue #16799: Switched from getopt to argparse style in regrtest's argument<br>
parsing.  Added more tests for regrtest's argument parsing.<br>
<br>
files:<br>
  Lib/test/regrtest.py      |  529 +++++++++++--------------<br>
  Lib/test/test_regrtest.py |  328 ++++++++++++---<br>
  Misc/NEWS                 |    3 +<br>
  3 files changed, 500 insertions(+), 360 deletions(-)<br>
<br>
<br>
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py<br>
--- a/Lib/test/regrtest.py<br>
+++ b/Lib/test/regrtest.py<br>
@@ -233,18 +233,20 @@<br>
     # We add help explicitly to control what argument group it renders under.<br>
     group.add_argument('-h', '--help', action='help',<br>
                        help='show this help message and exit')<br>
-    group.add_argument('--timeout', metavar='TIMEOUT',<br>
+    group.add_argument('--timeout', metavar='TIMEOUT', type=float,<br>
                         help='dump the traceback and exit if a test takes '<br>
                              'more than TIMEOUT seconds; disabled if TIMEOUT '<br>
                              'is negative or equals to zero')<br>
-    group.add_argument('--wait', action='store_true', help='wait for user '<br>
-                        'input, e.g., allow a debugger to be attached')<br>
+    group.add_argument('--wait', action='store_true',<br>
+                       help='wait for user input, e.g., allow a debugger '<br>
+                            'to be attached')<br>
     group.add_argument('--slaveargs', metavar='ARGS')<br>
-    group.add_argument('-S', '--start', metavar='START', help='the name of '<br>
-                        'the test at which to start.' + more_details)<br>
+    group.add_argument('-S', '--start', metavar='START',<br>
+                       help='the name of the test at which to start.' +<br>
+                            more_details)<br>
<br>
     group = parser.add_argument_group('Verbosity')<br>
-    group.add_argument('-v', '--verbose', action='store_true',<br>
+    group.add_argument('-v', '--verbose', action='count',<br>
                        help='run tests in verbose mode with output to stdout')<br>
     group.add_argument('-w', '--verbose2', action='store_true',<br>
                        help='re-run failed tests in verbose mode')<br>
@@ -254,7 +256,7 @@<br>
                        help='print traceback for failed tests')<br>
     group.add_argument('-q', '--quiet', action='store_true',<br>
                        help='no output unless one or more tests fail')<br>
-    group.add_argument('-o', '--slow', action='store_true',<br>
+    group.add_argument('-o', '--slow', action='store_true', dest='print_slow',<br>
                        help='print the slowest 10 tests')<br>
     group.add_argument('--header', action='store_true',<br>
                        help='print header with interpreter info')<br>
@@ -262,45 +264,60 @@<br>
     group = parser.add_argument_group('Selecting tests')<br>
     group.add_argument('-r', '--randomize', action='store_true',<br>
                        help='randomize test execution order.' + more_details)<br>
-    group.add_argument('--randseed', metavar='SEED', help='pass a random seed '<br>
-                       'to reproduce a previous random run')<br>
-    group.add_argument('-f', '--fromfile', metavar='FILE', help='read names '<br>
-                       'of tests to run from a file.' + more_details)<br>
+    group.add_argument('--randseed', metavar='SEED',<br>
+                       dest='random_seed', type=int,<br>
+                       help='pass a random seed to reproduce a previous '<br>
+                            'random run')<br>
+    group.add_argument('-f', '--fromfile', metavar='FILE',<br>
+                       help='read names of tests to run from a file.' +<br>
+                            more_details)<br>
     group.add_argument('-x', '--exclude', action='store_true',<br>
                        help='arguments are tests to *exclude*')<br>
-    group.add_argument('-s', '--single', action='store_true', help='single '<br>
-                       'step through a set of tests.' + more_details)<br>
-    group.add_argument('-m', '--match', metavar='PAT', help='match test cases '<br>
-                       'and methods with glob pattern PAT')<br>
-    group.add_argument('-G', '--failfast', action='store_true', help='fail as '<br>
-                       'soon as a test fails (only with -v or -W)')<br>
-    group.add_argument('-u', '--use', metavar='RES1,RES2,...', help='specify '<br>
-                       'which special resource intensive tests to run.' +<br>
-                       more_details)<br>
-    group.add_argument('-M', '--memlimit', metavar='LIMIT', help='run very '<br>
-                       'large memory-consuming tests.' + more_details)<br>
+    group.add_argument('-s', '--single', action='store_true',<br>
+                       help='single step through a set of tests.' +<br>
+                            more_details)<br>
+    group.add_argument('-m', '--match', metavar='PAT',<br>
+                       dest='match_tests',<br>
+                       help='match test cases and methods with glob pattern PAT')<br>
+    group.add_argument('-G', '--failfast', action='store_true',<br>
+                       help='fail as soon as a test fails (only with -v or -W)')<br>
+    group.add_argument('-u', '--use', metavar='RES1,RES2,...',<br>
+                       action='append', type=resources_list,<br>
+                       help='specify which special resource intensive tests '<br>
+                            'to run.' + more_details)<br>
+    group.add_argument('-M', '--memlimit', metavar='LIMIT',<br>
+                       help='run very large memory-consuming tests.' +<br>
+                            more_details)<br>
     group.add_argument('--testdir', metavar='DIR',<br>
+                       type=relative_filename,<br>
                        help='execute test files in the specified directory '<br>
                             '(instead of the Python stdlib test suite)')<br>
<br>
     group = parser.add_argument_group('Special runs')<br>
-    group.add_argument('-l', '--findleaks', action='store_true', help='if GC '<br>
-                       'is available detect tests that leak memory')<br>
+    group.add_argument('-l', '--findleaks', action='store_true',<br>
+                       help='if GC is available detect tests that leak memory')<br>
     group.add_argument('-L', '--runleaks', action='store_true',<br>
                        help='run the leaks(1) command just before exit.' +<br>
-                       more_details)<br>
+                            more_details)<br>
     group.add_argument('-R', '--huntrleaks', metavar='RUNCOUNTS',<br>
+                       type=huntrleaks,<br>
                        help='search for reference leaks (needs debug build, '<br>
                             'very slow).' + more_details)<br>
     group.add_argument('-j', '--multiprocess', metavar='PROCESSES',<br>
+                       dest='use_mp', type=int,<br>
                        help='run PROCESSES processes at once')<br>
-    group.add_argument('-T', '--coverage', action='store_true', help='turn on '<br>
-                       'code coverage tracing using the trace module')<br>
+    group.add_argument('-T', '--coverage', action='store_true',<br>
+                       dest='trace',<br>
+                       help='turn on code coverage tracing using the trace '<br>
+                            'module')<br>
     group.add_argument('-D', '--coverdir', metavar='DIR',<br>
+                       type=relative_filename,<br>
                        help='directory where coverage files are put')<br>
-    group.add_argument('-N', '--nocoverdir', action='store_true',<br>
+    group.add_argument('-N', '--nocoverdir',<br>
+                       action='store_const', const=None, dest='coverdir',<br>
                        help='put coverage files alongside modules')<br>
     group.add_argument('-t', '--threshold', metavar='THRESHOLD',<br>
+                       type=int,<br>
                        help='call gc.set_threshold(THRESHOLD)')<br>
     group.add_argument('-n', '--nowindows', action='store_true',<br>
                        help='suppress error message boxes on Windows')<br>
@@ -313,43 +330,103 @@<br>
<br>
     return parser<br>
<br>
-# TODO: remove this function as described in issue #16799, for example.<br>
-# We use this function since regrtest.main() was originally written to use<br>
-# getopt for parsing.<br>
-def _convert_namespace_to_getopt(ns):<br>
-    """Convert an argparse.Namespace object to a getopt-style opts list.<br>
+def relative_filename(string):<br>
+    # CWD is replaced with a temporary dir before calling main(), so we<br>
+    # join it with the saved CWD so it ends up where the user expects.<br>
+    return os.path.join(support.SAVEDCWD, string)<br>
<br>
-    The return value of this function mimics the first element of<br>
-    getopt.getopt()'s (opts, args) return value.  In addition, the (option,<br>
-    value) pairs in the opts list are sorted by option and use the long<br>
-    option string.  The args part of (opts, args) can be mimicked by the<br>
-    args attribute of the Namespace object we are using in regrtest.<br>
-    """<br>
-    opts = []<br>
-    args_dict = vars(ns)<br>
-    for key in sorted(args_dict.keys()):<br>
-        if key == 'args':<br>
+def huntrleaks(string):<br>
+    args = string.split(':')<br>
+    if len(args) not in (2, 3):<br>
+        raise argparse.ArgumentTypeError(<br>
+            'needs 2 or 3 colon-separated arguments')<br>
+    nwarmup = int(args[0]) if args[0] else 5<br>
+    ntracked = int(args[1]) if args[1] else 4<br>
+    fname = args[2] if len(args) > 2 and args[2] else 'reflog.txt'<br>
+    return nwarmup, ntracked, fname<br>
+<br>
+def resources_list(string):<br>
+    u = [x.lower() for x in string.split(',')]<br>
+    for r in u:<br>
+        if r == 'all' or r == 'none':<br>
             continue<br>
-        val = args_dict[key]<br>
-        # Don't continue if val equals '' because this means an option<br>
-        # accepting a value was provided the empty string.  Such values should<br>
-        # show up in the returned opts list.<br>
-        if val is None or val is False:<br>
-            continue<br>
-        if val is True:<br>
-            # Then an option with action store_true was passed. getopt<br>
-            # includes these with value '' in the opts list.<br>
-            val = ''<br>
-        opts.append(('--' + key, val))<br>
-    return opts<br>
+        if r[0] == '-':<br>
+            r = r[1:]<br>
+        if r not in RESOURCE_NAMES:<br>
+            raise argparse.ArgumentTypeError('invalid resource: ' + r)<br>
+    return u<br>
<br>
-<br>
-def main(tests=None, testdir=None, verbose=0, quiet=False,<br>
+def _parse_args(args, **kwargs):<br>
+    # Defaults<br>
+    ns = argparse.Namespace(testdir=None, verbose=0, quiet=False,<br>
          exclude=False, single=False, randomize=False, fromfile=None,<br>
          findleaks=False, use_resources=None, trace=False, coverdir='coverage',<br>
          runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,<br>
          random_seed=None, use_mp=None, verbose3=False, forever=False,<br>
-         header=False, failfast=False, match_tests=None):<br>
+         header=False, failfast=False, match_tests=None)<br>
+    for k, v in kwargs.items():<br>
+        if not hasattr(ns, k):<br>
+            raise TypeError('%r is an invalid keyword argument '<br>
+                            'for this function' % k)<br>
+        setattr(ns, k, v)<br>
+    if ns.use_resources is None:<br>
+        ns.use_resources = []<br>
+<br>
+    parser = _create_parser()<br>
+    parser.parse_args(args=args, namespace=ns)<br>
+<br>
+    if ns.single and ns.fromfile:<br>
+        parser.error("-s and -f don't go together!")<br>
+    if ns.use_mp and ns.trace:<br>
+        parser.error("-T and -j don't go together!")<br>
+    if ns.use_mp and ns.findleaks:<br>
+        parser.error("-l and -j don't go together!")<br>
+    if ns.use_mp and ns.memlimit:<br>
+        parser.error("-M and -j don't go together!")<br>
+    if ns.failfast and not (ns.verbose or ns.verbose3):<br>
+        parser.error("-G/--failfast needs either -v or -W")<br>
+<br>
+    if ns.quiet:<br>
+        ns.verbose = 0<br>
+    if ns.timeout is not None:<br>
+        if hasattr(faulthandler, 'dump_traceback_later'):<br>
+            if ns.timeout <= 0:<br>
+                ns.timeout = None<br>
+        else:<br>
+            print("Warning: The timeout option requires "<br>
+                  "faulthandler.dump_traceback_later")<br>
+            ns.timeout = None<br>
+    if ns.use_mp is not None:<br>
+        if ns.use_mp <= 0:<br>
+            # Use all cores + extras for tests that like to sleep<br>
+            ns.use_mp = 2 + (os.cpu_count() or 1)<br>
+        if ns.use_mp == 1:<br>
+            ns.use_mp = None<br>
+    if ns.use:<br>
+        for a in ns.use:<br>
+            for r in a:<br>
+                if r == 'all':<br>
+                    ns.use_resources[:] = RESOURCE_NAMES<br>
+                    continue<br>
+                if r == 'none':<br>
+                    del ns.use_resources[:]<br>
+                    continue<br>
+                remove = False<br>
+                if r[0] == '-':<br>
+                    remove = True<br>
+                    r = r[1:]<br>
+                if remove:<br>
+                    if r in ns.use_resources:<br>
+                        ns.use_resources.remove(r)<br>
+                elif r not in ns.use_resources:<br>
+                    ns.use_resources.append(r)<br>
+    if ns.random_seed is not None:<br>
+        ns.randomize = True<br>
+<br>
+    return ns<br>
+<br>
+<br>
+def main(tests=None, **kwargs):<br>
     """Execute a test suite.<br>
<br>
     This also parses command-line options and modifies its behavior<br>
@@ -372,7 +449,6 @@<br>
     directly to set the values that would normally be set by flags<br>
     on the command line.<br>
     """<br>
-<br>
     # Display the Python traceback on fatal errors (e.g. segfault)<br>
     faulthandler.enable(all_threads=True)<br>
<br>
@@ -389,174 +465,48 @@<br>
<br>
     support.record_original_stdout(sys.stdout)<br>
<br>
-    parser = _create_parser()<br>
-    ns = parser.parse_args()<br>
-    opts = _convert_namespace_to_getopt(ns)<br>
-    args = ns.args<br>
-    usage = parser.error<br>
+    ns = _parse_args(sys.argv[1:], **kwargs)<br>
<br>
-    # Defaults<br>
-    if random_seed is None:<br>
-        random_seed = random.randrange(10000000)<br>
-    if use_resources is None:<br>
-        use_resources = []<br>
-    debug = False<br>
-    start = None<br>
-    timeout = None<br>
-    for o, a in opts:<br>
-        if o in ('-v', '--verbose'):<br>
-            verbose += 1<br>
-        elif o in ('-w', '--verbose2'):<br>
-            verbose2 = True<br>
-        elif o in ('-d', '--debug'):<br>
-            debug = True<br>
-        elif o in ('-W', '--verbose3'):<br>
-            verbose3 = True<br>
-        elif o in ('-G', '--failfast'):<br>
-            failfast = True<br>
-        elif o in ('-q', '--quiet'):<br>
-            quiet = True;<br>
-            verbose = 0<br>
-        elif o in ('-x', '--exclude'):<br>
-            exclude = True<br>
-        elif o in ('-S', '--start'):<br>
-            start = a<br>
-        elif o in ('-s', '--single'):<br>
-            single = True<br>
-        elif o in ('-o', '--slow'):<br>
-            print_slow = True<br>
-        elif o in ('-r', '--randomize'):<br>
-            randomize = True<br>
-        elif o == '--randseed':<br>
-            randomize = True<br>
-            random_seed = int(a)<br>
-        elif o in ('-f', '--fromfile'):<br>
-            fromfile = a<br>
-        elif o in ('-m', '--match'):<br>
-            match_tests = a<br>
-        elif o in ('-l', '--findleaks'):<br>
-            findleaks = True<br>
-        elif o in ('-L', '--runleaks'):<br>
-            runleaks = True<br>
-        elif o in ('-t', '--threshold'):<br>
-            import gc<br>
-            gc.set_threshold(int(a))<br>
-        elif o in ('-T', '--coverage'):<br>
-            trace = True<br>
-        elif o in ('-D', '--coverdir'):<br>
-            # CWD is replaced with a temporary dir before calling main(), so we<br>
-            # need  join it with the saved CWD so it goes where the user expects.<br>
-            coverdir = os.path.join(support.SAVEDCWD, a)<br>
-        elif o in ('-N', '--nocoverdir'):<br>
-            coverdir = None<br>
-        elif o in ('-R', '--huntrleaks'):<br>
-            huntrleaks = a.split(':')<br>
-            if len(huntrleaks) not in (2, 3):<br>
-                print(a, huntrleaks)<br>
-                usage('-R takes 2 or 3 colon-separated arguments')<br>
-            if not huntrleaks[0]:<br>
-                huntrleaks[0] = 5<br>
-            else:<br>
-                huntrleaks[0] = int(huntrleaks[0])<br>
-            if not huntrleaks[1]:<br>
-                huntrleaks[1] = 4<br>
-            else:<br>
-                huntrleaks[1] = int(huntrleaks[1])<br>
-            if len(huntrleaks) == 2 or not huntrleaks[2]:<br>
-                huntrleaks[2:] = ["reflog.txt"]<br>
-            # Avoid false positives due to various caches<br>
-            # filling slowly with random data:<br>
-            warm_caches()<br>
-        elif o in ('-M', '--memlimit'):<br>
-            support.set_memlimit(a)<br>
-        elif o in ('-u', '--use'):<br>
-            u = [x.lower() for x in a.split(',')]<br>
-            for r in u:<br>
-                if r == 'all':<br>
-                    use_resources[:] = RESOURCE_NAMES<br>
-                    continue<br>
-                if r == 'none':<br>
-                    del use_resources[:]<br>
-                    continue<br>
-                remove = False<br>
-                if r[0] == '-':<br>
-                    remove = True<br>
-                    r = r[1:]<br>
-                if r not in RESOURCE_NAMES:<br>
-                    usage('Invalid -u/--use option: ' + a)<br>
-                if remove:<br>
-                    if r in use_resources:<br>
-                        use_resources.remove(r)<br>
-                elif r not in use_resources:<br>
-                    use_resources.append(r)<br>
-        elif o in ('-n', '--nowindows'):<br>
-            import msvcrt<br>
-            msvcrt.SetErrorMode(msvcrt.SEM_FAILCRITICALERRORS|<br>
-                    msvcrt.SEM_NOALIGNMENTFAULTEXCEPT|<br>
-                    msvcrt.SEM_NOGPFAULTERRORBOX|<br>
-                    msvcrt.SEM_NOOPENFILEERRORBOX)<br>
-            try:<br>
-                msvcrt.CrtSetReportMode<br>
-            except AttributeError:<br>
-                # release build<br>
-                pass<br>
-            else:<br>
-                for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:<br>
-                    msvcrt.CrtSetReportMode(m, msvcrt.CRTDBG_MODE_FILE)<br>
-                    msvcrt.CrtSetReportFile(m, msvcrt.CRTDBG_FILE_STDERR)<br>
-        elif o in ('-F', '--forever'):<br>
-            forever = True<br>
-        elif o in ('-j', '--multiprocess'):<br>
-            use_mp = int(a)<br>
-            if use_mp <= 0:<br>
-                # Use all cores + extras for tests that like to sleep<br>
-                use_mp = 2 + (os.cpu_count() or 1)<br>
-            if use_mp == 1:<br>
-                use_mp = None<br>
-        elif o == '--header':<br>
-            header = True<br>
-        elif o == '--slaveargs':<br>
-            args, kwargs = json.loads(a)<br>
-            try:<br>
-                result = runtest(*args, **kwargs)<br>
-            except KeyboardInterrupt:<br>
-                result = INTERRUPTED, ''<br>
-            except BaseException as e:<br>
-                traceback.print_exc()<br>
-                result = CHILD_ERROR, str(e)<br>
-            sys.stdout.flush()<br>
-            print()   # Force a newline (just in case)<br>
-            print(json.dumps(result))<br>
-            sys.exit(0)<br>
-        elif o == '--testdir':<br>
-            # CWD is replaced with a temporary dir before calling main(), so we<br>
-            # join it with the saved CWD so it ends up where the user expects.<br>
-            testdir = os.path.join(support.SAVEDCWD, a)<br>
-        elif o == '--timeout':<br>
-            if hasattr(faulthandler, 'dump_traceback_later'):<br>
-                timeout = float(a)<br>
-                if timeout <= 0:<br>
-                    timeout = None<br>
-            else:<br>
-                print("Warning: The timeout option requires "<br>
-                      "faulthandler.dump_traceback_later")<br>
-                timeout = None<br>
-        elif o == '--wait':<br>
-            input("Press any key to continue...")<br>
+    if ns.huntrleaks:<br>
+        # Avoid false positives due to various caches<br>
+        # filling slowly with random data:<br>
+        warm_caches()<br>
+    if ns.memlimit is not None:<br>
+        support.set_memlimit(ns.memlimit)<br>
+    if ns.threshold is not None:<br>
+        import gc<br>
+        gc.set_threshold(ns.threshold)<br>
+    if ns.nowindows:<br>
+        import msvcrt<br>
+        msvcrt.SetErrorMode(msvcrt.SEM_FAILCRITICALERRORS|<br>
+                            msvcrt.SEM_NOALIGNMENTFAULTEXCEPT|<br>
+                            msvcrt.SEM_NOGPFAULTERRORBOX|<br>
+                            msvcrt.SEM_NOOPENFILEERRORBOX)<br>
+        try:<br>
+            msvcrt.CrtSetReportMode<br>
+        except AttributeError:<br>
+            # release build<br>
+            pass<br>
         else:<br>
-            print(("No handler for option {}.  Please report this as a bug "<br>
-                   "at <a href="http://bugs.python.org" target="_blank">http://bugs.python.org</a>.").format(o), file=sys.stderr)<br>
-            sys.exit(1)<br>
-    if single and fromfile:<br>
-        usage("-s and -f don't go together!")<br>
-    if use_mp and trace:<br>
-        usage("-T and -j don't go together!")<br>
-    if use_mp and findleaks:<br>
-        usage("-l and -j don't go together!")<br>
-    if use_mp and support.max_memuse:<br>
-        usage("-M and -j don't go together!")<br>
-    if failfast and not (verbose or verbose3):<br>
-        usage("-G/--failfast needs either -v or -W")<br>
+            for m in [msvcrt.CRT_WARN, msvcrt.CRT_ERROR, msvcrt.CRT_ASSERT]:<br>
+                msvcrt.CrtSetReportMode(m, msvcrt.CRTDBG_MODE_FILE)<br>
+                msvcrt.CrtSetReportFile(m, msvcrt.CRTDBG_FILE_STDERR)<br>
+    if ns.wait:<br>
+        input("Press any key to continue...")<br>
+<br>
+    if ns.slaveargs is not None:<br>
+        args, kwargs = json.loads(ns.slaveargs)<br>
+        try:<br>
+            result = runtest(*args, **kwargs)<br>
+        except KeyboardInterrupt:<br>
+            result = INTERRUPTED, ''<br>
+        except BaseException as e:<br>
+            traceback.print_exc()<br>
+            result = CHILD_ERROR, str(e)<br>
+        sys.stdout.flush()<br>
+        print()   # Force a newline (just in case)<br>
+        print(json.dumps(result))<br>
+        sys.exit(0)<br>
<br>
     good = []<br>
     bad = []<br>
@@ -565,12 +515,12 @@<br>
     environment_changed = []<br>
     interrupted = False<br>
<br>
-    if findleaks:<br>
+    if ns.findleaks:<br>
         try:<br>
             import gc<br>
         except ImportError:<br>
             print('No GC available, disabling findleaks.')<br>
-            findleaks = False<br>
+            ns.findleaks = False<br>
         else:<br>
             # Uncomment the line below to report garbage that is not<br>
             # freeable by reference counting alone.  By default only<br>
@@ -578,42 +528,40 @@<br>
             #gc.set_debug(gc.DEBUG_SAVEALL)<br>
             found_garbage = []<br>
<br>
-    if single:<br>
+    if ns.single:<br>
         filename = os.path.join(TEMPDIR, 'pynexttest')<br>
         try:<br>
-            fp = open(filename, 'r')<br>
-            next_test = fp.read().strip()<br>
-            tests = [next_test]<br>
-            fp.close()<br>
+            with open(filename, 'r') as fp:<br>
+                next_test = fp.read().strip()<br>
+                tests = [next_test]<br>
         except OSError:<br>
             pass<br>
<br>
-    if fromfile:<br>
+    if ns.fromfile:<br>
         tests = []<br>
-        fp = open(os.path.join(support.SAVEDCWD, fromfile))<br>
-        count_pat = re.compile(r'\[\s*\d+/\s*\d+\]')<br>
-        for line in fp:<br>
-            line = count_pat.sub('', line)<br>
-            guts = line.split() # assuming no test has whitespace in its name<br>
-            if guts and not guts[0].startswith('#'):<br>
-                tests.extend(guts)<br>
-        fp.close()<br>
+        with open(os.path.join(support.SAVEDCWD, ns.fromfile)) as fp:<br>
+            count_pat = re.compile(r'\[\s*\d+/\s*\d+\]')<br>
+            for line in fp:<br>
+                line = count_pat.sub('', line)<br>
+                guts = line.split() # assuming no test has whitespace in its name<br>
+                if guts and not guts[0].startswith('#'):<br>
+                    tests.extend(guts)<br>
<br>
     # Strip .py extensions.<br>
-    removepy(args)<br>
+    removepy(ns.args)<br>
     removepy(tests)<br>
<br>
     stdtests = STDTESTS[:]<br>
     nottests = NOTTESTS.copy()<br>
-    if exclude:<br>
-        for arg in args:<br>
+    if ns.exclude:<br>
+        for arg in ns.args:<br>
             if arg in stdtests:<br>
                 stdtests.remove(arg)<br>
             nottests.add(arg)<br>
-        args = []<br>
+        ns.args = []<br>
<br>
     # For a partial run, we do not need to clutter the output.<br>
-    if verbose or header or not (quiet or single or tests or args):<br>
+    if ns.verbose or ns.header or not (ns.quiet or ns.single or tests or ns.args):<br>
         # Print basic platform information<br>
         print("==", platform.python_implementation(), *sys.version.split())<br>
         print("==  ", platform.platform(aliased=True),<br>
@@ -623,37 +571,39 @@<br>
<br>
     # if testdir is set, then we are not running the python tests suite, so<br>
     # don't add default tests to be executed or skipped (pass empty values)<br>
-    if testdir:<br>
-        alltests = findtests(testdir, list(), set())<br>
+    if ns.testdir:<br>
+        alltests = findtests(ns.testdir, list(), set())<br>
     else:<br>
-        alltests = findtests(testdir, stdtests, nottests)<br>
+        alltests = findtests(ns.testdir, stdtests, nottests)<br>
<br>
-    selected = tests or args or alltests<br>
-    if single:<br>
+    selected = tests or ns.args or alltests<br>
+    if ns.single:<br>
         selected = selected[:1]<br>
         try:<br>
             next_single_test = alltests[alltests.index(selected[0])+1]<br>
         except IndexError:<br>
             next_single_test = None<br>
     # Remove all the selected tests that precede start if it's set.<br>
-    if start:<br>
+    if ns.start:<br>
         try:<br>
-            del selected[:selected.index(start)]<br>
+            del selected[:selected.index(ns.start)]<br>
         except ValueError:<br>
-            print("Couldn't find starting test (%s), using all tests" % start)<br>
-    if randomize:<br>
-        random.seed(random_seed)<br>
-        print("Using random seed", random_seed)<br>
+            print("Couldn't find starting test (%s), using all tests" % ns.start)<br>
+    if ns.randomize:<br>
+        if ns.random_seed is None:<br>
+            ns.random_seed = random.randrange(10000000)<br>
+        random.seed(ns.random_seed)<br>
+        print("Using random seed", ns.random_seed)<br>
         random.shuffle(selected)<br>
-    if trace:<br>
+    if ns.trace:<br>
         import trace, tempfile<br>
         tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,<br>
                                          tempfile.gettempdir()],<br>
                              trace=False, count=True)<br>
<br>
     test_times = []<br>
-    support.verbose = verbose      # Tell tests to be moderately quiet<br>
-    support.use_resources = use_resources<br>
+    support.verbose = ns.verbose      # Tell tests to be moderately quiet<br>
+    support.use_resources = ns.use_resources<br>
     save_modules = sys.modules.keys()<br>
<br>
     def accumulate_result(test, result):<br>
@@ -671,7 +621,7 @@<br>
             skipped.append(test)<br>
             resource_denieds.append(test)<br>
<br>
-    if forever:<br>
+    if ns.forever:<br>
         def test_forever(tests=list(selected)):<br>
             while True:<br>
                 for test in tests:<br>
@@ -686,7 +636,7 @@<br>
         test_count = '/{}'.format(len(selected))<br>
         test_count_width = len(test_count) - 1<br>
<br>
-    if use_mp:<br>
+    if ns.use_mp:<br>
         try:<br>
             from threading import Thread<br>
         except ImportError:<br>
@@ -710,11 +660,12 @@<br>
                         output.put((None, None, None, None))<br>
                         return<br>
                     args_tuple = (<br>
-                        (test, verbose, quiet),<br>
-                        dict(huntrleaks=huntrleaks, use_resources=use_resources,<br>
-                             debug=debug, output_on_failure=verbose3,<br>
-                             timeout=timeout, failfast=failfast,<br>
-                             match_tests=match_tests)<br>
+                        (test, ns.verbose, ns.quiet),<br>
+                        dict(huntrleaks=ns.huntrleaks,<br>
+                             use_resources=ns.use_resources,<br>
+                             debug=ns.debug, output_on_failure=ns.verbose3,<br>
+                             timeout=ns.timeout, failfast=ns.failfast,<br>
+                             match_tests=ns.match_tests)<br>
                     )<br>
                     # -E is needed by some tests, e.g. test_import<br>
                     # Running the child from the same working directory ensures<br>
@@ -743,19 +694,19 @@<br>
             except BaseException:<br>
                 output.put((None, None, None, None))<br>
                 raise<br>
-        workers = [Thread(target=work) for i in range(use_mp)]<br>
+        workers = [Thread(target=work) for i in range(ns.use_mp)]<br>
         for worker in workers:<br>
             worker.start()<br>
         finished = 0<br>
         test_index = 1<br>
         try:<br>
-            while finished < use_mp:<br>
+            while finished < ns.use_mp:<br>
                 test, stdout, stderr, result = output.get()<br>
                 if test is None:<br>
                     finished += 1<br>
                     continue<br>
                 accumulate_result(test, result)<br>
-                if not quiet:<br>
+                if not ns.quiet:<br>
                     fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"<br>
                     print(fmt.format(<br>
                         test_count_width, test_index, test_count,<br>
@@ -778,29 +729,30 @@<br>
             worker.join()<br>
     else:<br>
         for test_index, test in enumerate(tests, 1):<br>
-            if not quiet:<br>
+            if not ns.quiet:<br>
                 fmt = "[{1:{0}}{2}/{3}] {4}" if bad else "[{1:{0}}{2}] {4}"<br>
                 print(fmt.format(<br>
                     test_count_width, test_index, test_count, len(bad), test))<br>
                 sys.stdout.flush()<br>
-            if trace:<br>
+            if ns.trace:<br>
                 # If we're tracing code coverage, then we don't exit with status<br>
                 # if on a false return value from main.<br>
-                tracer.runctx('runtest(test, verbose, quiet, timeout=timeout)',<br>
+                tracer.runctx('runtest(test, ns.verbose, ns.quiet, timeout=ns.timeout)',<br>
                               globals=globals(), locals=vars())<br>
             else:<br>
                 try:<br>
-                    result = runtest(test, verbose, quiet, huntrleaks, debug,<br>
-                                     output_on_failure=verbose3,<br>
-                                     timeout=timeout, failfast=failfast,<br>
-                                     match_tests=match_tests)<br>
+                    result = runtest(test, ns.verbose, ns.quiet,<br>
+                                     ns.huntrleaks, ns.debug,<br>
+                                     output_on_failure=ns.verbose3,<br>
+                                     timeout=ns.timeout, failfast=ns.failfast,<br>
+                                     match_tests=ns.match_tests)<br>
                     accumulate_result(test, result)<br>
                 except KeyboardInterrupt:<br>
                     interrupted = True<br>
                     break<br>
                 except:<br>
                     raise<br>
-            if findleaks:<br>
+            if ns.findleaks:<br>
                 gc.collect()<br>
                 if gc.garbage:<br>
                     print("Warning: test created", len(gc.garbage), end=' ')<br>
@@ -821,11 +773,11 @@<br>
         omitted = set(selected) - set(good) - set(bad) - set(skipped)<br>
         print(count(len(omitted), "test"), "omitted:")<br>
         printlist(omitted)<br>
-    if good and not quiet:<br>
+    if good and not ns.quiet:<br>
         if not bad and not skipped and not interrupted and len(good) > 1:<br>
             print("All", end=' ')<br>
         print(count(len(good), "test"), "OK.")<br>
-    if print_slow:<br>
+    if ns.print_slow:<br>
         test_times.sort(reverse=True)<br>
         print("10 slowest tests:")<br>
         for time, test in test_times[:10]:<br>
@@ -839,18 +791,19 @@<br>
         print("{} altered the execution environment:".format(<br>
                  count(len(environment_changed), "test")))<br>
         printlist(environment_changed)<br>
-    if skipped and not quiet:<br>
+    if skipped and not ns.quiet:<br>
         print(count(len(skipped), "test"), "skipped:")<br>
         printlist(skipped)<br>
<br>
-    if verbose2 and bad:<br>
+    if ns.verbose2 and bad:<br>
         print("Re-running failed tests in verbose mode")<br>
         for test in bad:<br>
             print("Re-running test %r in verbose mode" % test)<br>
             sys.stdout.flush()<br>
             try:<br>
-                verbose = True<br>
-                ok = runtest(test, True, quiet, huntrleaks, debug, timeout=timeout)<br>
+                ns.verbose = True<br>
+                ok = runtest(test, True, ns.quiet, ns.huntrleaks, ns.debug,<br>
+                             timeout=ns.timeout)<br>
             except KeyboardInterrupt:<br>
                 # print a newline separate from the ^C<br>
                 print()<br>
@@ -858,18 +811,18 @@<br>
             except:<br>
                 raise<br>
<br>
-    if single:<br>
+    if ns.single:<br>
         if next_single_test:<br>
             with open(filename, 'w') as fp:<br>
                 fp.write(next_single_test + '\n')<br>
         else:<br>
             os.unlink(filename)<br>
<br>
-    if trace:<br>
+    if ns.trace:<br>
         r = tracer.results()<br>
-        r.write_results(show_missing=True, summary=True, coverdir=coverdir)<br>
+        r.write_results(show_missing=True, summary=True, coverdir=ns.coverdir)<br>
<br>
-    if runleaks:<br>
+    if ns.runleaks:<br>
         os.system("leaks %d" % os.getpid())<br>
<br>
     sys.exit(len(bad) > 0 or interrupted)<br>
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py<br>
--- a/Lib/test/test_regrtest.py<br>
+++ b/Lib/test/test_regrtest.py<br>
@@ -4,97 +4,281 @@<br>
<br>
 import argparse<br>
 import getopt<br>
+import os.path<br>
 import unittest<br>
 from test import regrtest, support<br>
<br>
-def old_parse_args(args):<br>
-    """Parse arguments as regrtest did strictly prior to 3.4.<br>
-<br>
-    Raises getopt.GetoptError on bad arguments.<br>
-    """<br>
-    return getopt.getopt(args, 'hvqxsoS:rf:lu:t:TD:NLR:FdwWM:nj:Gm:',<br>
-        ['help', 'verbose', 'verbose2', 'verbose3', 'quiet',<br>
-         'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks',<br>
-         'use=', 'threshold=', 'coverdir=', 'nocoverdir',<br>
-         'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',<br>
-         'multiprocess=', 'coverage', 'slaveargs=', 'forever', 'debug',<br>
-         'start=', 'nowindows', 'header', 'testdir=', 'timeout=', 'wait',<br>
-         'failfast', 'match='])<br>
-<br>
 class ParseArgsTestCase(unittest.TestCase):<br>
<br>
-    """Test that regrtest's parsing code matches the prior getopt behavior."""<br>
+    """Test regrtest's argument parsing."""<br>
<br>
-    def _parse_args(self, args):<br>
-        # This is the same logic as that used in regrtest.main()<br>
-        parser = regrtest._create_parser()<br>
-        ns = parser.parse_args(args=args)<br>
-        opts = regrtest._convert_namespace_to_getopt(ns)<br>
-        return opts, ns.args<br>
+    def checkError(self, args, msg):<br>
+        with support.captured_stderr() as err, self.assertRaises(SystemExit):<br>
+            regrtest._parse_args(args)<br>
+        self.assertIn(msg, err.getvalue())<br>
<br>
-    def _check_args(self, args, expected=None):<br>
-        """<br>
-        The expected parameter is for cases when the behavior of the new<br>
-        parse_args differs from the old (but deliberately so).<br>
-        """<br>
-        if expected is None:<br>
-            try:<br>
-                expected = old_parse_args(args)<br>
-            except getopt.GetoptError:<br>
-                # Suppress usage string output when an argparse.ArgumentError<br>
-                # error is raised.<br>
-                with support.captured_stderr():<br>
-                    self.assertRaises(SystemExit, self._parse_args, args)<br>
-                return<br>
-        # The new parse_args() sorts by long option string.<br>
-        expected[0].sort()<br>
-        actual = self._parse_args(args)<br>
-        self.assertEqual(actual, expected)<br>
+    def test_help(self):<br>
+        for opt in '-h', '--help':<br>
+            with self.subTest(opt=opt):<br>
+                with support.captured_stdout() as out, \<br>
+                     self.assertRaises(SystemExit):<br>
+                    regrtest._parse_args([opt])<br>
+                self.assertIn('Run Python regression tests.', out.getvalue())<br>
+<br>
+    def test_timeout(self):<br>
+        ns = regrtest._parse_args(['--timeout', '4.2'])<br>
+        self.assertEqual(ns.timeout, 4.2)<br>
+        self.checkError(['--timeout'], 'expected one argument')<br>
+        self.checkError(['--timeout', 'foo'], 'invalid float value')<br>
+<br>
+    def test_wait(self):<br>
+        ns = regrtest._parse_args(['--wait'])<br>
+        self.assertTrue(ns.wait)<br>
+<br>
+    def test_slaveargs(self):<br>
+        ns = regrtest._parse_args(['--slaveargs', '[[], {}]'])<br>
+        self.assertEqual(ns.slaveargs, '[[], {}]')<br>
+        self.checkError(['--slaveargs'], 'expected one argument')<br>
+<br>
+    def test_start(self):<br>
+        for opt in '-S', '--start':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, 'foo'])<br>
+                self.assertEqual(ns.start, 'foo')<br>
+                self.checkError([opt], 'expected one argument')<br>
+<br>
+    def test_verbose(self):<br>
+        ns = regrtest._parse_args(['-v'])<br>
+        self.assertEqual(ns.verbose, 1)<br>
+        ns = regrtest._parse_args(['-vvv'])<br>
+        self.assertEqual(ns.verbose, 3)<br>
+        ns = regrtest._parse_args(['--verbose'])<br>
+        self.assertEqual(ns.verbose, 1)<br>
+        ns = regrtest._parse_args(['--verbose'] * 3)<br>
+        self.assertEqual(ns.verbose, 3)<br>
+        ns = regrtest._parse_args([])<br>
+        self.assertEqual(ns.verbose, 0)<br>
+<br>
+    def test_verbose2(self):<br>
+        for opt in '-w', '--verbose2':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.verbose2)<br>
+<br>
+    def test_verbose3(self):<br>
+        for opt in '-W', '--verbose3':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.verbose3)<br>
+<br>
+    def test_debug(self):<br>
+        for opt in '-d', '--debug':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.debug)<br>
+<br>
+    def test_quiet(self):<br>
+        for opt in '-q', '--quiet':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.quiet)<br>
+                self.assertEqual(ns.verbose, 0)<br>
+<br>
+    def test_slow(self):<br>
+        for opt in '-o', '--slow':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.print_slow)<br>
+<br>
+    def test_header(self):<br>
+        ns = regrtest._parse_args(['--header'])<br>
+        self.assertTrue(ns.header)<br>
+<br>
+    def test_randomize(self):<br>
+        for opt in '-r', '--randomize':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.randomize)<br>
+<br>
+    def test_randseed(self):<br>
+        ns = regrtest._parse_args(['--randseed', '12345'])<br>
+        self.assertEqual(ns.random_seed, 12345)<br>
+        self.assertTrue(ns.randomize)<br>
+        self.checkError(['--randseed'], 'expected one argument')<br>
+        self.checkError(['--randseed', 'foo'], 'invalid int value')<br>
+<br>
+    def test_fromfile(self):<br>
+        for opt in '-f', '--fromfile':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, 'foo'])<br>
+                self.assertEqual(ns.fromfile, 'foo')<br>
+                self.checkError([opt], 'expected one argument')<br>
+                self.checkError([opt, 'foo', '-s'], "don't go together")<br>
+<br>
+    def test_exclude(self):<br>
+        for opt in '-x', '--exclude':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.exclude)<br>
+<br>
+    def test_single(self):<br>
+        for opt in '-s', '--single':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.single)<br>
+                self.checkError([opt, '-f', 'foo'], "don't go together")<br>
+<br>
+    def test_match(self):<br>
+        for opt in '-m', '--match':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, 'pattern'])<br>
+                self.assertEqual(ns.match_tests, 'pattern')<br>
+                self.checkError([opt], 'expected one argument')<br>
+<br>
+    def test_failfast(self):<br>
+        for opt in '-G', '--failfast':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, '-v'])<br>
+                self.assertTrue(ns.failfast)<br>
+                ns = regrtest._parse_args([opt, '-W'])<br>
+                self.assertTrue(ns.failfast)<br>
+                self.checkError([opt], '-G/--failfast needs either -v or -W')<br>
+<br>
+    def test_use(self):<br>
+        for opt in '-u', '--use':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, 'gui,network'])<br>
+                self.assertEqual(ns.use_resources, ['gui', 'network'])<br>
+                ns = regrtest._parse_args([opt, 'gui,none,network'])<br>
+                self.assertEqual(ns.use_resources, ['network'])<br>
+                expected = list(regrtest.RESOURCE_NAMES)<br>
+                expected.remove('gui')<br>
+                ns = regrtest._parse_args([opt, 'all,-gui'])<br>
+                self.assertEqual(ns.use_resources, expected)<br>
+                self.checkError([opt], 'expected one argument')<br>
+                self.checkError([opt, 'foo'], 'invalid resource')<br>
+<br>
+    def test_memlimit(self):<br>
+        for opt in '-M', '--memlimit':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, '4G'])<br>
+                self.assertEqual(ns.memlimit, '4G')<br>
+                self.checkError([opt], 'expected one argument')<br>
+<br>
+    def test_testdir(self):<br>
+        ns = regrtest._parse_args(['--testdir', 'foo'])<br>
+        self.assertEqual(ns.testdir, os.path.join(support.SAVEDCWD, 'foo'))<br>
+        self.checkError(['--testdir'], 'expected one argument')<br>
+<br>
+    def test_findleaks(self):<br>
+        for opt in '-l', '--findleaks':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.findleaks)<br>
+<br>
+    def test_findleaks(self):<br>
+        for opt in '-L', '--runleaks':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.runleaks)<br>
+<br>
+    def test_findleaks(self):<br>
+        for opt in '-R', '--huntrleaks':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, ':'])<br>
+                self.assertEqual(ns.huntrleaks, (5, 4, 'reflog.txt'))<br>
+                ns = regrtest._parse_args([opt, '6:'])<br>
+                self.assertEqual(ns.huntrleaks, (6, 4, 'reflog.txt'))<br>
+                ns = regrtest._parse_args([opt, ':3'])<br>
+                self.assertEqual(ns.huntrleaks, (5, 3, 'reflog.txt'))<br>
+                ns = regrtest._parse_args([opt, '6:3:leaks.log'])<br>
+                self.assertEqual(ns.huntrleaks, (6, 3, 'leaks.log'))<br>
+                self.checkError([opt], 'expected one argument')<br>
+                self.checkError([opt, '6'],<br>
+                                'needs 2 or 3 colon-separated arguments')<br>
+                self.checkError([opt, 'foo:'], 'invalid huntrleaks value')<br>
+                self.checkError([opt, '6:foo'], 'invalid huntrleaks value')<br>
+<br>
+    def test_multiprocess(self):<br>
+        for opt in '-j', '--multiprocess':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, '2'])<br>
+                self.assertEqual(ns.use_mp, 2)<br>
+                self.checkError([opt], 'expected one argument')<br>
+                self.checkError([opt, 'foo'], 'invalid int value')<br>
+                self.checkError([opt, '2', '-T'], "don't go together")<br>
+                self.checkError([opt, '2', '-l'], "don't go together")<br>
+                self.checkError([opt, '2', '-M', '4G'], "don't go together")<br>
+<br>
+    def test_findleaks(self):<br>
+        for opt in '-T', '--coverage':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.trace)<br>
+<br>
+    def test_coverdir(self):<br>
+        for opt in '-D', '--coverdir':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, 'foo'])<br>
+                self.assertEqual(ns.coverdir,<br>
+                                 os.path.join(support.SAVEDCWD, 'foo'))<br>
+                self.checkError([opt], 'expected one argument')<br>
+<br>
+    def test_nocoverdir(self):<br>
+        for opt in '-N', '--nocoverdir':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertIsNone(ns.coverdir)<br>
+<br>
+    def test_threshold(self):<br>
+        for opt in '-t', '--threshold':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt, '1000'])<br>
+                self.assertEqual(ns.threshold, 1000)<br>
+                self.checkError([opt], 'expected one argument')<br>
+                self.checkError([opt, 'foo'], 'invalid int value')<br>
+<br>
+    def test_nowindows(self):<br>
+        for opt in '-n', '--nowindows':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.nowindows)<br>
+<br>
+    def test_forever(self):<br>
+        for opt in '-F', '--forever':<br>
+            with self.subTest(opt=opt):<br>
+                ns = regrtest._parse_args([opt])<br>
+                self.assertTrue(ns.forever)<br>
+<br>
<br>
     def test_unrecognized_argument(self):<br>
-        self._check_args(['--xxx'])<br>
-<br>
-    def test_value_not_provided(self):<br>
-        self._check_args(['--start'])<br>
-<br>
-    def test_short_option(self):<br>
-        # getopt returns the short option whereas argparse returns the long.<br>
-        expected = ([('--quiet', '')], [])<br>
-        self._check_args(['-q'], expected=expected)<br>
-<br>
-    def test_long_option(self):<br>
-        self._check_args(['--quiet'])<br>
+        self.checkError(['--xxx'], 'usage:')<br>
<br>
     def test_long_option__partial(self):<br>
-        self._check_args(['--qui'])<br>
+        ns = regrtest._parse_args(['--qui'])<br>
+        self.assertTrue(ns.quiet)<br>
+        self.assertEqual(ns.verbose, 0)<br>
<br>
     def test_two_options(self):<br>
-        self._check_args(['--quiet', '--exclude'])<br>
-<br>
-    def test_option_with_value(self):<br>
-        self._check_args(['--start', 'foo'])<br>
+        ns = regrtest._parse_args(['--quiet', '--exclude'])<br>
+        self.assertTrue(ns.quiet)<br>
+        self.assertEqual(ns.verbose, 0)<br>
+        self.assertTrue(ns.exclude)<br>
<br>
     def test_option_with_empty_string_value(self):<br>
-        self._check_args(['--start', ''])<br>
+        ns = regrtest._parse_args(['--start', ''])<br>
+        self.assertEqual(ns.start, '')<br>
<br>
     def test_arg(self):<br>
-        self._check_args(['foo'])<br>
+        ns = regrtest._parse_args(['foo'])<br>
+        self.assertEqual(ns.args, ['foo'])<br>
<br>
     def test_option_and_arg(self):<br>
-        self._check_args(['--quiet', 'foo'])<br>
+        ns = regrtest._parse_args(['--quiet', 'foo'])<br>
+        self.assertTrue(ns.quiet)<br>
+        self.assertEqual(ns.verbose, 0)<br>
+        self.assertEqual(ns.args, ['foo'])<br>
<br>
-    def test_fromfile(self):<br>
-        self._check_args(['--fromfile', 'file'])<br>
-<br>
-    def test_match(self):<br>
-        self._check_args(['--match', 'pattern'])<br>
-<br>
-    def test_randomize(self):<br>
-        self._check_args(['--randomize'])<br>
-<br>
-<br>
-def test_main():<br>
-    support.run_unittest(__name__)<br>
<br>
 if __name__ == '__main__':<br>
-    test_main()<br>
+    unittest.main()<br>
diff --git a/Misc/NEWS b/Misc/NEWS<br>
--- a/Misc/NEWS<br>
+++ b/Misc/NEWS<br>
@@ -153,6 +153,9 @@<br>
 Tests<br>
 -----<br>
<br>
+- Issue #16799: Switched from getopt to argparse style in regrtest's argument<br>
+  parsing.  Added more tests for regrtest's argument parsing.<br>
+<br>
 - Issue #18792: Use "127.0.0.1" or "::1" instead of "localhost" as much as<br>
   possible, since "localhost" goes through a DNS lookup under recent Windows<br>
   versions.<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Repository URL: <a href="http://hg.python.org/cpython" target="_blank">http://hg.python.org/cpython</a><br>
</font></span><br>_______________________________________________<br>
Python-checkins mailing list<br>
<a href="mailto:Python-checkins@python.org">Python-checkins@python.org</a><br>
<a href="http://mail.python.org/mailman/listinfo/python-checkins" target="_blank">http://mail.python.org/mailman/listinfo/python-checkins</a><br>
<br></blockquote></div><br></div></div></div>