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