Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coverage run: add a -o option #1304

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions coverage/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from coverage import env
from coverage.collector import CTracer
from coverage.config import CoverageConfig
from coverage.control import DEFAULT_DATAFILE
from coverage.data import combinable_files, debug_data_file
from coverage.debug import info_formatter, info_header, short_stack
from coverage.exceptions import _BaseCoverageException, _ExceptionDuringRun, NoSource
Expand Down Expand Up @@ -123,6 +124,17 @@ class Opts:
metavar="OUTFILE",
help="Write the JSON report to this file. Defaults to 'coverage.json'",
)
output_coverage = optparse.make_option(
'', '--data-file', action='store', dest="output_coverage",
metavar="OUTFILE",
help="Write the recorded coverage information to this file. Defaults to '.coverage'"
)
input_coverage = optparse.make_option(
'', '--data-file', action='store', dest="input_coverage",
metavar="INPUT",
help="Read coverage data for report generation from this file (needed if you have "
"specified -o previously). Defaults to '.coverage'"
)
json_pretty_print = optparse.make_option(
'', '--pretty-print', action='store_true',
help="Format the JSON for human readers.",
Expand Down Expand Up @@ -320,6 +332,8 @@ def get_prog_name(self):
Opts.rcfile,
]

REPORT_ARGS = [Opts.input_coverage]

CMDS = {
'annotate': CmdOptionParser(
"annotate",
Expand All @@ -328,7 +342,7 @@ def get_prog_name(self):
Opts.ignore_errors,
Opts.include,
Opts.omit,
] + GLOBAL_ARGS,
] + REPORT_ARGS + GLOBAL_ARGS,
usage="[options] [modules]",
description=(
"Make annotated copies of the given files, marking statements that are executed " +
Expand All @@ -342,6 +356,7 @@ def get_prog_name(self):
Opts.append,
Opts.keep,
Opts.quiet,
Opts.output_coverage
] + GLOBAL_ARGS,
usage="[options] <path1> <path2> ... <pathN>",
description=(
Expand Down Expand Up @@ -369,7 +384,7 @@ def get_prog_name(self):
),

'erase': CmdOptionParser(
"erase", GLOBAL_ARGS,
"erase", [Opts.input_coverage] + GLOBAL_ARGS,
description="Erase previously collected coverage data.",
),

Expand All @@ -395,7 +410,7 @@ def get_prog_name(self):
Opts.no_skip_covered,
Opts.skip_empty,
Opts.title,
] + GLOBAL_ARGS,
] + REPORT_ARGS + GLOBAL_ARGS,
usage="[options] [modules]",
description=(
"Create an HTML report of the coverage of the files. " +
Expand All @@ -416,7 +431,7 @@ def get_prog_name(self):
Opts.json_pretty_print,
Opts.quiet,
Opts.show_contexts,
] + GLOBAL_ARGS,
] + REPORT_ARGS + GLOBAL_ARGS,
usage="[options] [modules]",
description="Generate a JSON report of coverage results."
),
Expand All @@ -435,7 +450,7 @@ def get_prog_name(self):
Opts.skip_covered,
Opts.no_skip_covered,
Opts.skip_empty,
] + GLOBAL_ARGS,
] + REPORT_ARGS + GLOBAL_ARGS,
usage="[options] [modules]",
description="Report coverage statistics on modules."
),
Expand All @@ -450,6 +465,7 @@ def get_prog_name(self):
Opts.include,
Opts.module,
Opts.omit,
Opts.output_coverage,
Opts.pylib,
Opts.parallel_mode,
Opts.source,
Expand All @@ -469,7 +485,7 @@ def get_prog_name(self):
Opts.output_xml,
Opts.quiet,
Opts.skip_empty,
] + GLOBAL_ARGS,
] + REPORT_ARGS + GLOBAL_ARGS,
usage="[options] [modules]",
description="Generate an XML report of coverage results."
),
Expand Down Expand Up @@ -572,8 +588,11 @@ def command_line(self, argv):
else:
concurrency = None

data_file = getattr(options, "output_coverage", None) \
or getattr(options, "input_coverage", None)
# Do something.
self.coverage = Coverage(
data_file=data_file or DEFAULT_DATAFILE,
data_suffix=options.parallel_mode,
cover_pylib=options.pylib,
timid=options.timid,
Expand Down
7 changes: 4 additions & 3 deletions coverage/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ def override_config(cov, **kwargs):
cov.config = original_config


_DEFAULT_DATAFILE = DefaultValue("MISSING")
DEFAULT_DATAFILE = DefaultValue("MISSING")
_DEFAULT_DATAFILE = DEFAULT_DATAFILE # Just in case, for backwards compatibility

class Coverage:
"""Programmatic access to coverage.py.
Expand Down Expand Up @@ -101,7 +102,7 @@ def current(cls):
return None

def __init__(
self, data_file=_DEFAULT_DATAFILE, data_suffix=None, cover_pylib=None,
self, data_file=DEFAULT_DATAFILE, data_suffix=None, cover_pylib=None,
auto_data=False, timid=None, branch=None, config_file=True,
source=None, source_pkgs=None, omit=None, include=None, debug=None,
concurrency=None, check_preimported=False, context=None,
Expand Down Expand Up @@ -198,7 +199,7 @@ def __init__(
# data_file=None means no disk file at all. data_file missing means
# use the value from the config file.
self._no_disk = data_file is None
if data_file is _DEFAULT_DATAFILE:
if data_file is DEFAULT_DATAFILE:
data_file = None

self.config = None
Expand Down
25 changes: 25 additions & 0 deletions tests/test_cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import coverage
import coverage.cmdline
from coverage import env
from coverage.control import DEFAULT_DATAFILE
from coverage.config import CoverageConfig
from coverage.exceptions import _ExceptionDuringRun
from coverage.version import __url__
Expand Down Expand Up @@ -53,6 +54,7 @@ class BaseCmdLineTest(CoverageTest):
contexts=None, pretty_print=None, show_contexts=None,
)
_defaults.Coverage(
data_file=DEFAULT_DATAFILE,
cover_pylib=None, data_suffix=None, timid=None, branch=None,
config_file=True, source=None, include=None, omit=None, debug=None,
concurrency=None, check_preimported=True, context=None, messages=True,
Expand Down Expand Up @@ -245,6 +247,11 @@ def test_combine(self):
cov.combine(None, strict=True, keep=False)
cov.save()
""")
self.cmd_executes("combine --data-file=foo.cov", """\
cov = Coverage(data_file="foo.cov")
cov.combine(None, strict=True, keep=False)
cov.save()
""")

def test_combine_doesnt_confuse_options_with_args(self):
# https://github.com/nedbat/coveragepy/issues/385
Expand Down Expand Up @@ -300,6 +307,10 @@ def test_erase(self):
cov = Coverage()
cov.erase()
""")
self.cmd_executes("erase --data-file=foo.cov", """\
cov = Coverage(data_file="foo.cov")
cov.erase()
""")

def test_version(self):
# coverage --version
Expand Down Expand Up @@ -510,6 +521,11 @@ def test_report(self):
cov.load()
cov.report(sort='-foo')
""")
self.cmd_executes("report --data-file=foo.cov.2", """\
cov = Coverage(data_file="foo.cov.2")
cov.load()
cov.report(show_missing=None)
""")

def test_run(self):
# coverage run [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...]
Expand Down Expand Up @@ -636,6 +652,15 @@ def test_run(self):
cov.stop()
cov.save()
""")
self.cmd_executes("run --data-file=output.coverage foo.py", """\
cov = Coverage(data_file="output.coverage")
runner = PyRunner(['foo.py'], as_module=False)
runner.prepare()
cov.start()
runner.run()
cov.stop()
cov.save()
""")

def test_multiprocessing_needs_config_file(self):
# You can't use command-line args to add options to multiprocessing
Expand Down