Skip to content

Commit a0f6692

Browse files
authored
Add combine --keep (#1110)
* Add combine --keep Related to #1108 * Fix unit tests * Fix line too long * Fix line too long
1 parent 0143891 commit a0f6692

File tree

8 files changed

+51
-14
lines changed

8 files changed

+51
-14
lines changed

coverage/cmdline.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class Opts(object):
3131
'-a', '--append', action='store_true',
3232
help="Append coverage data to .coverage, otherwise it starts clean each time.",
3333
)
34+
keep = optparse.make_option(
35+
'', '--keep', action='store_true',
36+
help="Keep combined coverage files, otherwise they are deleted.",
37+
)
3438
branch = optparse.make_option(
3539
'', '--branch', action='store_true',
3640
help="Measure branch coverage in addition to statement coverage.",
@@ -215,6 +219,7 @@ def __init__(self, *args, **kwargs):
215219
help=None,
216220
ignore_errors=None,
217221
include=None,
222+
keep=None,
218223
module=None,
219224
omit=None,
220225
contexts=None,
@@ -333,6 +338,7 @@ def get_prog_name(self):
333338
"combine",
334339
[
335340
Opts.append,
341+
Opts.keep,
336342
] + GLOBAL_ARGS,
337343
usage="[options] <path1> <path2> ... <pathN>",
338344
description=(
@@ -585,7 +591,7 @@ def command_line(self, argv):
585591
if options.append:
586592
self.coverage.load()
587593
data_dirs = args or None
588-
self.coverage.combine(data_dirs, strict=True)
594+
self.coverage.combine(data_dirs, strict=True, keep=bool(options.keep))
589595
self.coverage.save()
590596
return OK
591597

coverage/control.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ def save(self):
659659
data = self.get_data()
660660
data.write()
661661

662-
def combine(self, data_paths=None, strict=False):
662+
def combine(self, data_paths=None, strict=False, keep=False):
663663
"""Combine together a number of similarly-named coverage data files.
664664
665665
All coverage data files whose name starts with `data_file` (from the
@@ -674,6 +674,8 @@ def combine(self, data_paths=None, strict=False):
674674
If `strict` is true, then it is an error to attempt to combine when
675675
there are no data files to combine.
676676
677+
If `keep` is true, then combined data files won't be deleted.
678+
677679
.. versionadded:: 4.0
678680
The `data_paths` parameter.
679681
@@ -694,7 +696,8 @@ def combine(self, data_paths=None, strict=False):
694696
for pattern in paths[1:]:
695697
aliases.add(pattern, result)
696698

697-
combine_parallel_data(self._data, aliases=aliases, data_paths=data_paths, strict=strict)
699+
combine_parallel_data(self._data,
700+
aliases=aliases, data_paths=data_paths, strict=strict, keep=keep)
698701

699702
def get_data(self):
700703
"""Get the collected data.

coverage/data.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def add_data_to_hash(data, filename, hasher):
5252
hasher.update(data.file_tracer(filename))
5353

5454

55-
def combine_parallel_data(data, aliases=None, data_paths=None, strict=False):
55+
def combine_parallel_data(data, aliases=None, data_paths=None, strict=False, keep=False):
5656
"""Combine a number of data files together.
5757
5858
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):
6868
If `data_paths` is not provided, then the directory portion of
6969
`data.filename` is used as the directory to search for data files.
7070
71-
Every data file found and combined is then deleted from disk. If a file
71+
Unless `keep` is True every data file found and combined is then deleted from disk. If a file
7272
cannot be read, a warning will be issued, and the file will not be
7373
deleted.
7474
@@ -116,9 +116,10 @@ def combine_parallel_data(data, aliases=None, data_paths=None, strict=False):
116116
else:
117117
data.update(new_data, aliases=aliases)
118118
files_combined += 1
119-
if data._debug.should('dataio'):
120-
data._debug.write("Deleting combined data file %r" % (f,))
121-
file_be_gone(f)
119+
if not keep:
120+
if data._debug.should('dataio'):
121+
data._debug.write("Deleting combined data file %r" % (f,))
122+
file_be_gone(f)
122123

123124
if strict and not files_combined:
124125
raise CoverageException("No usable data files")

doc/help/combine.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
Options:
1414
-a, --append Append coverage data to .coverage, otherwise it starts
1515
clean each time.
16+
--keep Keep combined coverage files, otherwise they are deleted.
1617
--debug=OPTS Debug options, separated by commas. [env: COVERAGE_DEBUG]
1718
-h, --help Get help on this command.
1819
--rcfile=RCFILE Specify configuration file. By default '.coveragerc',

doc/python-coverage.1.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ COMMAND REFERENCE
109109
Combine data from multiple coverage files collected with ``run -p``.
110110
The combined results are written to a single file representing the
111111
union of the data.
112+
Unless --keep is provided the combined coverage files are deleted.
112113

113114
If `PATH` is specified, they are files or directories containing data to
114115
be combined.
@@ -119,6 +120,9 @@ COMMAND REFERENCE
119120
Append coverage data to .coverage, otherwise it starts clean each
120121
time.
121122

123+
\--keep
124+
Keep combined coverage file.
125+
122126
**debug** `TOPIC` ...
123127

124128
Display information about the internals of coverage.py, for diagnosing

tests/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ def test_combining_twice(self):
442442

443443
cov2 = coverage.Coverage()
444444
with self.assertRaisesRegex(CoverageException, r"No data to combine"):
445-
cov2.combine(strict=True)
445+
cov2.combine(strict=True, keep=False)
446446

447447
cov3 = coverage.Coverage()
448448
cov3.combine()

tests/test_cmdline.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,33 +218,33 @@ def test_combine(self):
218218
# coverage combine with args
219219
self.cmd_executes("combine datadir1", """\
220220
cov = Coverage()
221-
cov.combine(["datadir1"], strict=True)
221+
cov.combine(["datadir1"], strict=True, keep=False)
222222
cov.save()
223223
""")
224224
# coverage combine, appending
225225
self.cmd_executes("combine --append datadir1", """\
226226
cov = Coverage()
227227
cov.load()
228-
cov.combine(["datadir1"], strict=True)
228+
cov.combine(["datadir1"], strict=True, keep=False)
229229
cov.save()
230230
""")
231231
# coverage combine without args
232232
self.cmd_executes("combine", """\
233233
cov = Coverage()
234-
cov.combine(None, strict=True)
234+
cov.combine(None, strict=True, keep=False)
235235
cov.save()
236236
""")
237237

238238
def test_combine_doesnt_confuse_options_with_args(self):
239239
# https://github.com/nedbat/coveragepy/issues/385
240240
self.cmd_executes("combine --rcfile cov.ini", """\
241241
cov = Coverage(config_file='cov.ini')
242-
cov.combine(None, strict=True)
242+
cov.combine(None, strict=True, keep=False)
243243
cov.save()
244244
""")
245245
self.cmd_executes("combine --rcfile cov.ini data1 data2/more", """\
246246
cov = Coverage(config_file='cov.ini')
247-
cov.combine(["data1", "data2/more"], strict=True)
247+
cov.combine(["data1", "data2/more"], strict=True, keep=False)
248248
cov.save()
249249
""")
250250

tests/test_process.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,28 @@ def test_combine_parallel_data_no_append(self):
244244
data.read()
245245
self.assertEqual(line_counts(data)['b_or_c.py'], 7)
246246

247+
def test_combine_parallel_data_keep(self):
248+
self.make_b_or_c_py()
249+
out = self.run_command("coverage run -p b_or_c.py b")
250+
self.assertEqual(out, 'done\n')
251+
self.assert_doesnt_exist(".coverage")
252+
self.assert_file_count(".coverage.*", 1)
253+
254+
out = self.run_command("coverage run -p b_or_c.py c")
255+
self.assertEqual(out, 'done\n')
256+
self.assert_doesnt_exist(".coverage")
257+
258+
# After two -p runs, there should be two .coverage.machine.123 files.
259+
self.assert_file_count(".coverage.*", 2)
260+
261+
# Combine the parallel coverage data files into .coverage with the keep flag.
262+
self.run_command("coverage combine --keep")
263+
264+
# After combining, the .coverage file & the original combined file should still be there.
265+
self.assert_exists(".coverage")
266+
self.assert_file_count(".coverage.*", 2)
267+
268+
247269
def test_append_data(self):
248270
self.make_b_or_c_py()
249271

0 commit comments

Comments
 (0)