diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2009-09-12 09:46:24 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2009-09-12 09:46:24 -0400 |
commit | 269c6d3d361729a73fed9070c3d084bb37382e6a (patch) | |
tree | 14ad631acb813243e06f492ee6e76de67ff4a652 /coverage/cmdline.py | |
parent | 8df78f7c12b7ee230538b36dfa948afb4c57f13f (diff) | |
download | python-coveragepy-git-269c6d3d361729a73fed9070c3d084bb37382e6a.tar.gz |
Major changes to introduce new command line syntax.
Diffstat (limited to 'coverage/cmdline.py')
-rw-r--r-- | coverage/cmdline.py | 252 |
1 files changed, 174 insertions, 78 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index f7f92ee9..6481f229 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -4,65 +4,63 @@ import optparse, sys from coverage.execfile import run_python_file -USAGE = r""" -Coverage version %(__version__)s -Measure, collect, and report on code coverage in Python programs. - -Usage: - -coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] - Execute the module, passing the given command-line arguments, collecting - coverage data. With the -p option, include the machine name and process - id in the .coverage file name. With -L, measure coverage even inside the - Python installed library, which isn't done by default. With --timid, use a - simpler but slower trace method. - -coverage -e - Erase collected coverage data. - -coverage -c - Combine data from multiple coverage files (as created by -p option above) - and store it into a single file representing the union of the coverage. - -coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] - Report on the statement coverage for the given files. With the -m - option, show line numbers of the statements that weren't executed. - -coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] - Create an HTML report of the coverage of the given files. Each file gets - its own page, with the file listing decorated to show executed, excluded, - and missed lines. - -coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] - Make annotated copies of the given files, marking statements that - are executed with > and statements that are missed with !. --d DIR - Write output files for -b or -a to this directory. - --i Ignore errors while reporting or annotating. - --o DIR,... - Omit reporting or annotating files when their filename path starts with - a directory listed in the omit list. - e.g. coverage -i -r -o c:\python25,lib\enthought\traits - --h Print this help. - -Coverage data is saved in the file .coverage by default. Set the -COVERAGE_FILE environment variable to save it somewhere else. -""".strip() +class opts: + directory = optparse.Option( + '-d', '--directory', action='store', dest='directory', + ) + help = optparse.Option( + '-h', '--help', action='store_true', dest='help', + ) + ignore_errors = optparse.Option( + '-i', '--ignore-errors', action='store_true', + ) + pylib = optparse.Option( + '-L', '--pylib', action='store_true', + help="Measure coverage even inside the Python installed library, which isn't done by default." + ) + show_missing = optparse.Option( + '-m', '--show-missing', action='store_true', + ) + omit = optparse.Option( + '-o', '--omit', action='store', + ) + parallel_mode = optparse.Option( + '-p', '--parallel-mode', action='store_true', + help="Include the machine name and process id in the .coverage data file name." + ) + timid = optparse.Option( + '', '--timid', action='store_true', + help="Use a simpler but slower trace method. Use this if you get seemingly impossible results!" + ) + +class CoverageOptionParser(optparse.OptionParser, object): + """Base OptionParser for coverage. + + Problems don't exit the program. + Defaults are initialized for all options. + + """ -class OptionParser(optparse.OptionParser, object): - """A better OptionParser: Problems don't exit the program.""" - - def __init__(self, help_fn, *args, **kwargs): - super(OptionParser, self).__init__( + def __init__(self, *args, **kwargs): + super(CoverageOptionParser, self).__init__( add_help_option=False, *args, **kwargs ) + self.set_defaults( + actions=[], + directory=None, + help=None, + ignore_errors=None, + omit=None, + parallel_mode=None, + pylib=None, + show_missing=None, + timid=None, + ) + self.disable_interspersed_args() - self.help_fn = help_fn + self.help_fn = None class OptionParserError(Exception): """Used to stop the optparse error handler ending the process.""" @@ -75,7 +73,7 @@ class OptionParser(optparse.OptionParser, object): """ try: - options, args = super(OptionParser, self).parse_args(args, options) + options, args = super(CoverageOptionParser, self).parse_args(args, options) except self.OptionParserError: return False, None, None return True, options, args @@ -86,43 +84,67 @@ class OptionParser(optparse.OptionParser, object): raise self.OptionParserError -class ClassicOptionParser(OptionParser): +class ClassicOptionParser(CoverageOptionParser): """Command-line parser for coverage.py classic arguments.""" - def __init__(self, help_fn, *args, **kwargs): - super(ClassicOptionParser, self).__init__(help_fn, *args, **kwargs) - - self.set_defaults(actions=[]) - - self.help_fn = help_fn + def __init__(self): + super(ClassicOptionParser, self).__init__() self.add_action('-a', '--annotate', 'annotate') self.add_action('-b', '--html', 'html') self.add_action('-c', '--combine', 'combine') - self.add_option('-d', '--directory', action='store', dest='directory') self.add_action('-e', '--erase', 'erase') - self.add_option('-h', '--help', action='store_true', dest='help') - self.add_option('-i', '--ignore-errors', action='store_true') - self.add_option('-L', '--pylib', action='store_true') - self.add_option('-m', '--show-missing', action='store_true') - self.add_option('-p', '--parallel-mode', action='store_true') self.add_action('-r', '--report', 'report') self.add_action('-x', '--execute', 'execute') - self.add_option('-o', '--omit', action='store') - self.add_option('', '--timid', action='store_true') - def add_action(self, dash, dashdash, action): + self.add_options([ + opts.directory, + opts.help, + opts.ignore_errors, + opts.pylib, + opts.show_missing, + opts.omit, + opts.parallel_mode, + opts.timid, + ]) + + def add_action(self, dash, dashdash, action_code): """Add a specialized option that is the action to execute.""" option = self.add_option(dash, dashdash, action='callback', callback=self._append_action ) - option.action_code = action + option.action_code = action_code def _append_action(self, option, opt_unused, value_unused, parser): """Callback for an option that adds to the `actions` list.""" parser.values.actions.append(option.action_code) +class NewOptionParser(CoverageOptionParser): + """Parse one of the new-style commands for coverage.py.""" + + def __init__(self, action): + super(NewOptionParser, self).__init__( + usage="coverage %s [blah]" % action + ) + self.set_defaults(actions=[action]) + + +class RunOptionParser(NewOptionParser): + def __init__(self): + super(RunOptionParser, self).__init__("execute") + self.add_options([ + opts.pylib, + opts.parallel_mode, + opts.timid, + ]) + + +CMDS = { + 'run': RunOptionParser(), +} + + class CoverageScript: """The command-line interface to Coverage.""" @@ -142,30 +164,50 @@ class CoverageScript: self.coverage = None - def help(self, error=None): - """Display an error message, or the usage for Coverage.""" + def help(self, error=None, topic=None): + """Display an error message, or the named topic.""" + assert error or topic if error: print error print "Use -h for help." else: - print USAGE % self.covpkg.__dict__ + print HELP_TOPICS[topic].strip() % self.covpkg.__dict__ def command_line(self, argv): """The bulk of the command line interface to Coverage. `argv` is the argument list to process. - + + Returns 0 if all is well, 1 if something went wrong. + """ # Collect the command-line options. OK, ERR = 0, 1 - parser = ClassicOptionParser(self.help_fn) + if not argv: + self.help_fn( + "Code coverage for Python. Use -h for help." + ) + return OK + + # The command syntax we parse depends on the first argument. Classic + # syntax always starts with an option. + if argv[0].startswith('-'): + parser = ClassicOptionParser() + else: + parser = CMDS.get(argv[0]) + if not parser: + self.help_fn("Unknown command: '%s'" % argv[0]) + return ERR + argv = argv[1:] + + parser.help_fn = self.help_fn ok, options, args = parser.parse_args(argv) if not ok: return ERR if options.help: - self.help_fn() + self.help_fn(topic='usage') return OK # Check for conflicts and problems in the options. @@ -242,7 +284,61 @@ class CoverageScript: directory=options.directory, **report_args) return OK - + + +HELP_TOPICS = { + +'usage': r""" +Coverage version %(__version__)s +Measure, collect, and report on code coverage in Python programs. + +Usage: + +coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] + Execute the module, passing the given command-line arguments, collecting + coverage data. With the -p option, include the machine name and process + id in the .coverage file name. With -L, measure coverage even inside the + Python installed library, which isn't done by default. With --timid, use a + simpler but slower trace method. + +coverage -e + Erase collected coverage data. + +coverage -c + Combine data from multiple coverage files (as created by -p option above) + and store it into a single file representing the union of the coverage. + +coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] + Report on the statement coverage for the given files. With the -m + option, show line numbers of the statements that weren't executed. + +coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] + Create an HTML report of the coverage of the given files. Each file gets + its own page, with the file listing decorated to show executed, excluded, + and missed lines. + +coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] + Make annotated copies of the given files, marking statements that + are executed with > and statements that are missed with !. + +-d DIR + Write output files for -b or -a to this directory. + +-i Ignore errors while reporting or annotating. + +-o DIR,... + Omit reporting or annotating files when their filename path starts with + a directory listed in the omit list. + e.g. coverage -i -r -o c:\python25,lib\enthought\traits + +-h Print this help. + +Coverage data is saved in the file .coverage by default. Set the +COVERAGE_FILE environment variable to save it somewhere else. +""", + +} + def main(): """The main entrypoint to Coverage. |