summaryrefslogtreecommitdiff
path: root/coverage/data.py
diff options
context:
space:
mode:
Diffstat (limited to 'coverage/data.py')
-rw-r--r--coverage/data.py86
1 files changed, 43 insertions, 43 deletions
diff --git a/coverage/data.py b/coverage/data.py
index 452ce73d..1b883750 100644
--- a/coverage/data.py
+++ b/coverage/data.py
@@ -2,53 +2,40 @@
import os
-from coverage.backward import pickle, sorted # pylint: disable-msg=W0622
+from coverage.backward import pickle, sorted # pylint: disable-msg=W0622
class CoverageData(object):
"""Manages collected coverage data, including file storage.
-
+
The data file format is a pickled dict, with these keys:
-
+
* collector: a string identifying the collecting software
* lines: a dict mapping filenames to sorted lists of line numbers
executed:
{ 'file1': [17,23,45], 'file2': [1,2,3], ... }
-
+
* arcs: a dict mapping filenames to sorted lists of line number pairs:
{ 'file1': [(17,23), (17,25), (25,26)], ... }
"""
-
- # Name of the data file (unless environment variable is set).
- filename_default = ".coverage"
-
- # Environment variable naming the data file.
- filename_env = "COVERAGE_FILE"
- def __init__(self, basename=None, suffix=None, collector=None):
+ def __init__(self, basename=None, collector=None):
"""Create a CoverageData.
-
+
`basename` is the name of the file to use for storing data.
-
- `suffix` is a suffix to append to the base file name. This can be used
- for multiple or parallel execution, so that many coverage data files
- can exist simultaneously.
`collector` is a string describing the coverage measurement software.
"""
- self.collector = collector
-
+ self.collector = collector or 'unknown'
+
self.use_file = True
# Construct the filename that will be used for data file storage, if we
# ever do any file storage.
- self.filename = (basename or
- os.environ.get(self.filename_env, self.filename_default))
- if suffix:
- self.filename += suffix
+ self.filename = basename or ".coverage"
self.filename = os.path.abspath(self.filename)
# A map from canonical Python source file name to a dictionary in
@@ -61,14 +48,14 @@ class CoverageData(object):
# }
#
self.lines = {}
-
+
# A map from canonical Python source file name to a dictionary with an
# entry for each pair of line numbers forming an arc:
#
# { filename: { (l1,l2): None, ... }, ...}
#
self.arcs = {}
-
+
def usefile(self, use_file=True):
"""Set whether or not to use a disk file for data."""
self.use_file = use_file
@@ -80,10 +67,20 @@ class CoverageData(object):
else:
self.lines, self.arcs = {}, {}
- def write(self):
- """Write the collected coverage data to a file."""
+ def write(self, suffix=None):
+ """Write the collected coverage data to a file.
+
+ `suffix` is a suffix to append to the base file name. This can be used
+ for multiple or parallel execution, so that many coverage data files
+ can exist simultaneously. A dot will be used to join the base name and
+ the suffix.
+
+ """
if self.use_file:
- self.write_file(self.filename)
+ filename = self.filename
+ if suffix:
+ filename += "." + suffix
+ self.write_file(filename)
def erase(self):
"""Erase the data, both in this object, and from its file storage."""
@@ -92,7 +89,7 @@ class CoverageData(object):
os.remove(self.filename)
self.lines = {}
self.arcs = {}
-
+
def line_data(self):
"""Return the map from filenames to lists of line numbers executed."""
return dict(
@@ -104,11 +101,11 @@ class CoverageData(object):
return dict(
[(f, sorted(amap.keys())) for f, amap in self.arcs.items()]
)
-
+
def write_file(self, filename):
"""Write the coverage data to `filename`."""
- # Create the file data.
+ # Create the file data.
data = {}
data['lines'] = self.line_data()
@@ -141,10 +138,10 @@ class CoverageData(object):
def _read_file(self, filename):
"""Return the stored coverage data from the given file.
-
+
Returns two values, suitable for assigning to `self.lines` and
`self.arcs`.
-
+
"""
lines = {}
arcs = {}
@@ -167,35 +164,38 @@ class CoverageData(object):
def combine_parallel_data(self):
"""Combine a number of data files together.
-
+
Treat `self.filename` as a file prefix, and combine the data from all
- of the data files starting with that prefix.
-
+ of the data files starting with that prefix plus a dot.
+
"""
data_dir, local = os.path.split(self.filename)
+ localdot = local + '.'
for f in os.listdir(data_dir or '.'):
- if f.startswith(local):
+ if f.startswith(localdot):
full_path = os.path.join(data_dir, f)
new_lines, new_arcs = self._read_file(full_path)
for filename, file_data in new_lines.items():
self.lines.setdefault(filename, {}).update(file_data)
for filename, file_data in new_arcs.items():
self.arcs.setdefault(filename, {}).update(file_data)
+ if f != local:
+ os.remove(full_path)
def add_line_data(self, line_data):
"""Add executed line data.
-
+
`line_data` is { filename: { lineno: None, ... }, ...}
-
+
"""
for filename, linenos in line_data.items():
self.lines.setdefault(filename, {}).update(linenos)
def add_arc_data(self, arc_data):
"""Add measured arc data.
-
+
`arc_data` is { filename: { (l1,l2): None, ... }, ...}
-
+
"""
for filename, arcs in arc_data.items():
self.arcs.setdefault(filename, {}).update(arcs)
@@ -206,7 +206,7 @@ class CoverageData(object):
def executed_lines(self, filename):
"""A map containing all the line numbers executed in `filename`.
-
+
If `filename` hasn't been collected at all (because it wasn't executed)
then return an empty map.
@@ -219,11 +219,11 @@ class CoverageData(object):
def summary(self, fullpath=False):
"""Return a dict summarizing the coverage data.
-
+
Keys are based on the filenames, and values are the number of executed
lines. If `fullpath` is true, then the keys are the full pathnames of
the files, otherwise they are the basenames of the files.
-
+
"""
summ = {}
if fullpath: