summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉric Larivière <elarivie@users.noreply.github.com>2021-01-30 17:55:11 -0500
committerGitHub <noreply@github.com>2021-01-30 17:55:11 -0500
commita0f6692f5cc9344ae790300dcc0cf743ac9abbd3 (patch)
tree9884b4de9221850ffe5a10f919322d2ffeabdcef
parent0143891b04c0c800fe1a508ab424cbe825f4210b (diff)
downloadpython-coveragepy-git-a0f6692f5cc9344ae790300dcc0cf743ac9abbd3.tar.gz
Add combine --keep (#1110)
* Add combine --keep Related to https://github.com/nedbat/coveragepy/issues/1108 * Fix unit tests * Fix line too long * Fix line too long
-rw-r--r--coverage/cmdline.py8
-rw-r--r--coverage/control.py7
-rw-r--r--coverage/data.py11
-rw-r--r--doc/help/combine.rst1
-rw-r--r--doc/python-coverage.1.txt4
-rw-r--r--tests/test_api.py2
-rw-r--r--tests/test_cmdline.py10
-rw-r--r--tests/test_process.py22
8 files changed, 51 insertions, 14 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index 9c9ae868..11bc5d99 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -31,6 +31,10 @@ class Opts(object):
'-a', '--append', action='store_true',
help="Append coverage data to .coverage, otherwise it starts clean each time.",
)
+ keep = optparse.make_option(
+ '', '--keep', action='store_true',
+ help="Keep combined coverage files, otherwise they are deleted.",
+ )
branch = optparse.make_option(
'', '--branch', action='store_true',
help="Measure branch coverage in addition to statement coverage.",
@@ -215,6 +219,7 @@ class CoverageOptionParser(optparse.OptionParser, object):
help=None,
ignore_errors=None,
include=None,
+ keep=None,
module=None,
omit=None,
contexts=None,
@@ -333,6 +338,7 @@ CMDS = {
"combine",
[
Opts.append,
+ Opts.keep,
] + GLOBAL_ARGS,
usage="[options] <path1> <path2> ... <pathN>",
description=(
@@ -585,7 +591,7 @@ class CoverageScript(object):
if options.append:
self.coverage.load()
data_dirs = args or None
- self.coverage.combine(data_dirs, strict=True)
+ self.coverage.combine(data_dirs, strict=True, keep=bool(options.keep))
self.coverage.save()
return OK
diff --git a/coverage/control.py b/coverage/control.py
index 8d129bcb..c952afcd 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -659,7 +659,7 @@ class Coverage(object):
data = self.get_data()
data.write()
- def combine(self, data_paths=None, strict=False):
+ def combine(self, data_paths=None, strict=False, keep=False):
"""Combine together a number of similarly-named coverage data files.
All coverage data files whose name starts with `data_file` (from the
@@ -674,6 +674,8 @@ class Coverage(object):
If `strict` is true, then it is an error to attempt to combine when
there are no data files to combine.
+ If `keep` is true, then combined data files won't be deleted.
+
.. versionadded:: 4.0
The `data_paths` parameter.
@@ -694,7 +696,8 @@ class Coverage(object):
for pattern in paths[1:]:
aliases.add(pattern, result)
- combine_parallel_data(self._data, aliases=aliases, data_paths=data_paths, strict=strict)
+ combine_parallel_data(self._data,
+ aliases=aliases, data_paths=data_paths, strict=strict, keep=keep)
def get_data(self):
"""Get the collected data.
diff --git a/coverage/data.py b/coverage/data.py
index 82bf1d41..5dd1dfe3 100644
--- a/coverage/data.py
+++ b/coverage/data.py
@@ -52,7 +52,7 @@ def add_data_to_hash(data, filename, hasher):
hasher.update(data.file_tracer(filename))
-def combine_parallel_data(data, aliases=None, data_paths=None, strict=False):
+def combine_parallel_data(data, aliases=None, data_paths=None, strict=False, keep=False):
"""Combine a number of data files together.
Treat `data.filename` as a file prefix, and combine the data from all
@@ -68,7 +68,7 @@ def combine_parallel_data(data, aliases=None, data_paths=None, strict=False):
If `data_paths` is not provided, then the directory portion of
`data.filename` is used as the directory to search for data files.
- Every data file found and combined is then deleted from disk. If a file
+ Unless `keep` is True every data file found and combined is then deleted from disk. If a file
cannot be read, a warning will be issued, and the file will not be
deleted.
@@ -116,9 +116,10 @@ def combine_parallel_data(data, aliases=None, data_paths=None, strict=False):
else:
data.update(new_data, aliases=aliases)
files_combined += 1
- if data._debug.should('dataio'):
- data._debug.write("Deleting combined data file %r" % (f,))
- file_be_gone(f)
+ if not keep:
+ if data._debug.should('dataio'):
+ data._debug.write("Deleting combined data file %r" % (f,))
+ file_be_gone(f)
if strict and not files_combined:
raise CoverageException("No usable data files")
diff --git a/doc/help/combine.rst b/doc/help/combine.rst
index 35180cdd..c35d5b93 100644
--- a/doc/help/combine.rst
+++ b/doc/help/combine.rst
@@ -13,6 +13,7 @@
Options:
-a, --append Append coverage data to .coverage, otherwise it starts
clean each time.
+ --keep Keep combined coverage files, otherwise they are deleted.
--debug=OPTS Debug options, separated by commas. [env: COVERAGE_DEBUG]
-h, --help Get help on this command.
--rcfile=RCFILE Specify configuration file. By default '.coveragerc',
diff --git a/doc/python-coverage.1.txt b/doc/python-coverage.1.txt
index 0bbd44d0..10a8927a 100644
--- a/doc/python-coverage.1.txt
+++ b/doc/python-coverage.1.txt
@@ -109,6 +109,7 @@ COMMAND REFERENCE
Combine data from multiple coverage files collected with ``run -p``.
The combined results are written to a single file representing the
union of the data.
+ Unless --keep is provided the combined coverage files are deleted.
If `PATH` is specified, they are files or directories containing data to
be combined.
@@ -119,6 +120,9 @@ COMMAND REFERENCE
Append coverage data to .coverage, otherwise it starts clean each
time.
+ \--keep
+ Keep combined coverage file.
+
**debug** `TOPIC` ...
Display information about the internals of coverage.py, for diagnosing
diff --git a/tests/test_api.py b/tests/test_api.py
index f8b7b4b2..62fd9ebc 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -442,7 +442,7 @@ class ApiTest(CoverageTest):
cov2 = coverage.Coverage()
with self.assertRaisesRegex(CoverageException, r"No data to combine"):
- cov2.combine(strict=True)
+ cov2.combine(strict=True, keep=False)
cov3 = coverage.Coverage()
cov3.combine()
diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py
index 374adb0d..3b11881b 100644
--- a/tests/test_cmdline.py
+++ b/tests/test_cmdline.py
@@ -218,20 +218,20 @@ class CmdLineTest(BaseCmdLineTest):
# coverage combine with args
self.cmd_executes("combine datadir1", """\
cov = Coverage()
- cov.combine(["datadir1"], strict=True)
+ cov.combine(["datadir1"], strict=True, keep=False)
cov.save()
""")
# coverage combine, appending
self.cmd_executes("combine --append datadir1", """\
cov = Coverage()
cov.load()
- cov.combine(["datadir1"], strict=True)
+ cov.combine(["datadir1"], strict=True, keep=False)
cov.save()
""")
# coverage combine without args
self.cmd_executes("combine", """\
cov = Coverage()
- cov.combine(None, strict=True)
+ cov.combine(None, strict=True, keep=False)
cov.save()
""")
@@ -239,12 +239,12 @@ class CmdLineTest(BaseCmdLineTest):
# https://github.com/nedbat/coveragepy/issues/385
self.cmd_executes("combine --rcfile cov.ini", """\
cov = Coverage(config_file='cov.ini')
- cov.combine(None, strict=True)
+ cov.combine(None, strict=True, keep=False)
cov.save()
""")
self.cmd_executes("combine --rcfile cov.ini data1 data2/more", """\
cov = Coverage(config_file='cov.ini')
- cov.combine(["data1", "data2/more"], strict=True)
+ cov.combine(["data1", "data2/more"], strict=True, keep=False)
cov.save()
""")
diff --git a/tests/test_process.py b/tests/test_process.py
index e4886156..b44147a3 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -244,6 +244,28 @@ class ProcessTest(CoverageTest):
data.read()
self.assertEqual(line_counts(data)['b_or_c.py'], 7)
+ def test_combine_parallel_data_keep(self):
+ self.make_b_or_c_py()
+ out = self.run_command("coverage run -p b_or_c.py b")
+ self.assertEqual(out, 'done\n')
+ self.assert_doesnt_exist(".coverage")
+ self.assert_file_count(".coverage.*", 1)
+
+ out = self.run_command("coverage run -p b_or_c.py c")
+ self.assertEqual(out, 'done\n')
+ self.assert_doesnt_exist(".coverage")
+
+ # After two -p runs, there should be two .coverage.machine.123 files.
+ self.assert_file_count(".coverage.*", 2)
+
+ # Combine the parallel coverage data files into .coverage with the keep flag.
+ self.run_command("coverage combine --keep")
+
+ # After combining, the .coverage file & the original combined file should still be there.
+ self.assert_exists(".coverage")
+ self.assert_file_count(".coverage.*", 2)
+
+
def test_append_data(self):
self.make_b_or_c_py()