summaryrefslogtreecommitdiff
path: root/coverage/data.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-03-05 21:21:43 -0500
committerNed Batchelder <ned@nedbatchelder.com>2009-03-05 21:21:43 -0500
commit0cc8fd18714cb214327a0a58b704401a9efdf8dc (patch)
tree0a6ac59eaf1b7acaf26053a5f3c69304b9ddbda3 /coverage/data.py
downloadpython-coveragepy-git-0cc8fd18714cb214327a0a58b704401a9efdf8dc.tar.gz
Initial coverage.py 3.0 beta 1
Diffstat (limited to 'coverage/data.py')
-rw-r--r--coverage/data.py122
1 files changed, 122 insertions, 0 deletions
diff --git a/coverage/data.py b/coverage/data.py
new file mode 100644
index 00000000..5d14a337
--- /dev/null
+++ b/coverage/data.py
@@ -0,0 +1,122 @@
+"""Coverage data for coverage.py"""
+
+import os, marshal, socket, types
+
+class CoverageData:
+ """Manages collected coverage data."""
+ # 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):
+ self.filename = None
+ self.use_file = True
+
+ # A map from canonical Python source file name to a dictionary in
+ # which there's an entry for each line number that has been
+ # executed:
+ #
+ # {
+ # 'filename1.py': { 12: True, 47: True, ... },
+ # ...
+ # }
+ #
+ self.executed = {}
+
+ def usefile(self, use_file=True, filename_default=None):
+ self.use_file = use_file
+ if filename_default and not self.filename:
+ self.filename_default = filename_default
+
+ def read(self, parallel=False):
+ """Read coverage data from the coverage data file (if it exists)."""
+ data = {}
+ if self.use_file and not self.filename:
+ self.filename = os.environ.get(
+ self.filename_env, self.filename_default)
+ if parallel:
+ self.filename += "." + socket.gethostname()
+ self.filename += "." + str(os.getpid())
+ if os.path.exists(self.filename):
+ data = self._read_file(self.filename)
+ self.executed = data
+
+ def write(self):
+ """Write the collected coverage data to a file."""
+ if self.use_file and self.filename:
+ self.write_file(self.filename)
+
+ def erase(self):
+ if self.filename and os.path.exists(self.filename):
+ os.remove(self.filename)
+
+ def write_file(self, filename):
+ """Write the coverage data to `filename`."""
+ f = open(filename, 'wb')
+ try:
+ marshal.dump(self.executed, f)
+ finally:
+ f.close()
+
+ def read_file(self, filename):
+ self.executed = self._read_file(filename)
+
+ def _read_file(self, filename):
+ """ Return the stored coverage data from the given file.
+ """
+ try:
+ fdata = open(filename, 'rb')
+ executed = marshal.load(fdata)
+ fdata.close()
+ if isinstance(executed, types.DictType):
+ return executed
+ else:
+ return {}
+ except:
+ return {}
+
+ def combine_parallel_data(self):
+ """ Treat self.filename as a file prefix, and combine the data from all
+ of the files starting with that prefix.
+ """
+ data_dir, local = os.path.split(self.filename)
+ for f in os.listdir(data_dir or '.'):
+ if f.startswith(local):
+ full_path = os.path.join(data_dir, f)
+ file_data = self._read_file(full_path)
+ self._combine_data(file_data)
+
+ def _combine_data(self, new_data):
+ """Combine the `new_data` into `executed`."""
+ for filename, file_data in new_data.items():
+ self.executed.setdefault(filename, {}).update(file_data)
+
+ def add_raw_data(self, data_points):
+ """Add raw data.
+
+ `data_points` is (filename, lineno) pairs.
+
+ """
+ for filename, lineno in data_points:
+ self.executed.setdefault(filename, {})[lineno] = True
+
+ def executed_lines(self, filename):
+ """Return a mapping object such that "lineno in obj" is true if that
+ line number had been executed in `filename`.
+ """
+ # TODO: Write a better description.
+ return self.executed[filename]
+
+ def summary(self):
+ """Return a dict summarizing the coverage data.
+
+ Keys are the basename of the filenames, and values are the number of
+ executed lines. This is useful in the unit tests.
+
+ """
+ summ = {}
+ for filename, lines in self.executed.items():
+ summ[os.path.basename(filename)] = len(lines)
+ return summ