From 7efd4f50062f750df145102fc07c87fc49599bbe Mon Sep 17 00:00:00 2001 From: Christine Lytwynec Date: Tue, 21 Apr 2015 11:28:13 -0400 Subject: Added ability to combine coverage data files from multiple directories into one file via command line args. --- coverage/cmdline.py | 5 +++-- coverage/control.py | 4 ++-- coverage/data.py | 40 +++++++++++++++++++++++++--------------- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'coverage') diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 2be3294..c611e03 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -249,7 +249,7 @@ CMDS = { ), 'combine': CmdOptionParser("combine", GLOBAL_ARGS, - usage = " ", + usage = " ... ", description = "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." @@ -430,7 +430,8 @@ class CoverageScript(object): self.do_run(options, args) if options.action == "combine": - self.coverage.combine() + data_dirs = argv if argv else None + self.coverage.combine(data_dirs) self.coverage.save() # Remaining actions are reporting, with some common options. diff --git a/coverage/control.py b/coverage/control.py index 563925e..4a9ac72 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -717,7 +717,7 @@ class Coverage(object): self._harvest_data() self.data.write(suffix=data_suffix) - def combine(self): + def combine(self, data_dirs=None): """Combine together a number of similarly-named coverage data files. All coverage data files whose name starts with `data_file` (from the @@ -733,7 +733,7 @@ class Coverage(object): result = paths[0] for pattern in paths[1:]: aliases.add(pattern, result) - self.data.combine_parallel_data(aliases=aliases) + self.data.combine_parallel_data(aliases=aliases, data_dirs=data_dirs) def _harvest_data(self): """Get the collected data and reset the collector. diff --git a/coverage/data.py b/coverage/data.py index 2c5d351..ed79f79 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -1,5 +1,6 @@ """Coverage data for Coverage.""" +import glob import os from coverage.backward import iitems, pickle @@ -190,7 +191,7 @@ class CoverageData(object): pass return lines, arcs, plugins - def combine_parallel_data(self, aliases=None): + def combine_parallel_data(self, aliases=None, data_dirs=None): """Combine a number of data files together. Treat `self.filename` as a file prefix, and combine the data from all @@ -199,23 +200,32 @@ class CoverageData(object): If `aliases` is provided, it's a `PathAliases` object that is used to re-map paths to match the local machine's. + If `data_dirs` is provided, then it combines the data files from each + directory into a single file. + """ aliases = aliases or PathAliases() data_dir, local = os.path.split(self.filename) - localdot = local + '.' - for f in os.listdir(data_dir or '.'): - if f.startswith(localdot): - full_path = os.path.join(data_dir, f) - new_lines, new_arcs, new_plugins = self._read_file(full_path) - for filename, file_data in iitems(new_lines): - filename = aliases.map(filename) - self.lines.setdefault(filename, {}).update(file_data) - for filename, file_data in iitems(new_arcs): - filename = aliases.map(filename) - self.arcs.setdefault(filename, {}).update(file_data) - self.plugins.update(new_plugins) - if f != local: - os.remove(full_path) + localdot = local + '.*' + + data_dirs = data_dirs or [data_dir] or ['.'] + files_to_combine = [] + for d in data_dirs: + pattern = os.path.join(os.path.abspath(d), localdot) + files_to_combine.extend(glob.glob(pattern)) + + for f in files_to_combine: + new_lines, new_arcs, new_plugins = self._read_file(f) + for filename, file_data in iitems(new_lines): + filename = aliases.map(filename) + self.lines.setdefault(filename, {}).update(file_data) + for filename, file_data in iitems(new_arcs): + filename = aliases.map(filename) + self.arcs.setdefault(filename, {}).update(file_data) + self.plugins.update(new_plugins) + + if os.path.basename(f) != local: + os.remove(f) def add_line_data(self, line_data): """Add executed line data. -- cgit v1.2.1 From 161556f47ec6b8f7c0232c21fdbdd7cc25bd3d8e Mon Sep 17 00:00:00 2001 From: Christine Lytwynec Date: Wed, 22 Apr 2015 11:45:55 -0400 Subject: Update docstring and command line help text. --- coverage/cmdline.py | 5 ++++- coverage/control.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'coverage') diff --git a/coverage/cmdline.py b/coverage/cmdline.py index c611e03..66a76fa 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -252,7 +252,10 @@ CMDS = { usage = " ... ", description = "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." + "file representing the union of the data. The positional " + "arguments are directories from which the data files should be " + "combined. By default, only data files in the current directory " + "are combined." ), 'debug': CmdOptionParser("debug", GLOBAL_ARGS, diff --git a/coverage/control.py b/coverage/control.py index 4a9ac72..2c8d384 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -724,6 +724,10 @@ class Coverage(object): coverage() constructor) will be read, and combined together into the current measurements. + `data_dirs` is a list of directories from which data files should be + combined. If no list is passed, then the data files from the current + directory will be combined. + """ self._init() aliases = None -- cgit v1.2.1 From aee7fba6b17bbcf9510e5891d154a52069b783b3 Mon Sep 17 00:00:00 2001 From: Christine Lytwynec Date: Thu, 23 Apr 2015 16:25:08 -0400 Subject: Update tests --- coverage/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'coverage') diff --git a/coverage/data.py b/coverage/data.py index ed79f79..fa43ff7 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -208,7 +208,7 @@ class CoverageData(object): data_dir, local = os.path.split(self.filename) localdot = local + '.*' - data_dirs = data_dirs or [data_dir] or ['.'] + data_dirs = data_dirs or [data_dir] files_to_combine = [] for d in data_dirs: pattern = os.path.join(os.path.abspath(d), localdot) -- cgit v1.2.1 From e114efc35ad2c2134f7d4c24a7a4fac286f9e50a Mon Sep 17 00:00:00 2001 From: Christine Lytwynec Date: Fri, 24 Apr 2015 12:46:32 -0400 Subject: remove unneeded conditional --- coverage/data.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'coverage') diff --git a/coverage/data.py b/coverage/data.py index fa43ff7..8a699b5 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -223,9 +223,7 @@ class CoverageData(object): filename = aliases.map(filename) self.arcs.setdefault(filename, {}).update(file_data) self.plugins.update(new_plugins) - - if os.path.basename(f) != local: - os.remove(f) + os.remove(f) def add_line_data(self, line_data): """Add executed line data. -- cgit v1.2.1