diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2009-04-18 20:01:57 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2009-04-18 20:01:57 -0400 |
commit | b97380c4a3a97ac2469ace44005dc63857daf245 (patch) | |
tree | 72d2bc9e6ba280c21c2bdc41d0f764b2fcd5ee39 /coverage/data.py | |
parent | d0a794abfae0fb1d115c5979c9a8dc5c07a12b9c (diff) | |
download | python-coveragepy-git-b97380c4a3a97ac2469ace44005dc63857daf245.tar.gz |
New more flexible data storage.
Diffstat (limited to 'coverage/data.py')
-rw-r--r-- | coverage/data.py | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/coverage/data.py b/coverage/data.py index 19e00087..721f9c0f 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -3,6 +3,14 @@ import os, types import cPickle as pickle +# Data file format is a pickled dict, with these keys: +# +# collector: a string identifying the collecting software +# +# lines: a dict mapping filenames to lists of line numbers executed: +# { 'file1': [17,23,45], 'file2': [1,2,3], ... } + + class CoverageData: """Manages collected coverage data.""" # Name of the data file (unless environment variable is set). @@ -11,7 +19,10 @@ class CoverageData: # Environment variable naming the data file. filename_env = "COVERAGE_FILE" - def __init__(self): + def __init__(self, collector=None): + + self.collector = collector + self.use_file = True self.filename = None self.suffix = None @@ -25,7 +36,7 @@ class CoverageData: # ... # } # - self.executed = {} + self.lines = {} def usefile(self, use_file=True): """Set whether or not to use a disk file for data.""" @@ -41,6 +52,7 @@ class CoverageData: self.suffix = suffix def _make_filename(self): + """Construct the filename that will be used for data file storage.""" assert self.use_file if not self.filename: self.filename = os.environ.get( @@ -54,7 +66,7 @@ class CoverageData: if self.use_file: self._make_filename() data = self._read_file(self.filename) - self.executed = data + self.lines = data def write(self): """Write the collected coverage data to a file.""" @@ -63,22 +75,35 @@ class CoverageData: self.write_file(self.filename) def erase(self): + """Erase the data, both in this object, and from its file storage.""" if self.use_file: self._make_filename() if self.filename and os.path.exists(self.filename): os.remove(self.filename) - self.executed = {} + self.lines = {} def write_file(self, filename): """Write the coverage data to `filename`.""" - f = open(filename, 'wb') + + # Create the file data. + data = {} + + data['lines'] = dict( + [(f, list(linemap.keys())) for f, linemap in self.lines.items()] + ) + + if self.collector: + data['collector'] = self.collector + + # Write the pickle to the file. + fdata = open(filename, 'wb') try: - pickle.dump(self.executed, f) + pickle.dump(data, fdata) finally: - f.close() + fdata.close() def read_file(self, filename): - self.executed = self._read_file(filename) + self.lines = self._read_file(filename) def _read_file(self, filename): """ Return the stored coverage data from the given file. @@ -86,11 +111,16 @@ class CoverageData: try: fdata = open(filename, 'rb') try: - executed = pickle.load(fdata) + data = pickle.load(fdata) finally: fdata.close() - if isinstance(executed, types.DictType): - return executed + if isinstance(data, types.DictType): + # Unpack the 'lines' item. + lines = dict([ + (f, dict([(l, True) for l in linenos])) + for f,linenos in data['lines'].items() + ]) + return lines else: return {} except: @@ -107,7 +137,7 @@ class CoverageData: full_path = os.path.join(data_dir, f) new_data = self._read_file(full_path) for filename, file_data in new_data.items(): - self.executed.setdefault(filename, {}).update(file_data) + self.lines.setdefault(filename, {}).update(file_data) def add_line_data(self, data_points): """Add executed line data. @@ -116,11 +146,11 @@ class CoverageData: """ for filename, lineno in data_points: - self.executed.setdefault(filename, {})[lineno] = True + self.lines.setdefault(filename, {})[lineno] = True def executed_files(self): """A list of all files that had been measured as executed.""" - return self.executed.keys() + return self.lines.keys() def executed_lines(self, filename): """A map containing all the line numbers executed in `filename`. @@ -128,7 +158,7 @@ class CoverageData: If `filename` hasn't been collected at all (because it wasn't executed) then return an empty map. """ - return self.executed.get(filename) or {} + return self.lines.get(filename) or {} def summary(self): """Return a dict summarizing the coverage data. @@ -138,6 +168,6 @@ class CoverageData: """ summ = {} - for filename, lines in self.executed.items(): + for filename, lines in self.lines.items(): summ[os.path.basename(filename)] = len(lines) return summ |