diff options
-rw-r--r-- | coverage/cmdline.py | 2 | ||||
-rw-r--r-- | coverage/control.py | 43 | ||||
-rw-r--r-- | coverage/data.py | 29 | ||||
-rw-r--r-- | test/test_api.py | 45 | ||||
-rw-r--r-- | test/test_data.py | 6 |
5 files changed, 99 insertions, 26 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 89d0b270..81901a85 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -137,7 +137,7 @@ class CoverageScript: # Do something. self.coverage = self.covpkg.coverage( - parallel_mode = settings.get('parallel-mode'), + data_suffix = bool(settings.get('parallel-mode')), cover_stdlib = settings.get('stdlib') ) self.coverage.get_ready() diff --git a/coverage/control.py b/coverage/control.py index 697e732b..22efa2ff 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -11,11 +11,24 @@ from coverage.misc import format_lines, CoverageException from coverage.summary import SummaryReporter class coverage: - def __init__(self, parallel_mode=False, cover_stdlib=False): + """Programmatic access to Coverage. + + """ + def __init__(self, data_file=None, data_suffix=False, cover_stdlib=False): + """Create a new coverage measurement context. + + `data_file` is the base name of the data file to use, defaulting to + ".coverage". `data_suffix` is appended to `data_file` to create the + final file name. If `data_suffix` is simply True, then a suffix is + created with the machine and process identity included. + + `cover_stdlib` is a boolean determining whether Python code installed + with the Python interpreter is measured. + + """ from coverage.collector import Collector from coverage import __version__ - self.parallel_mode = parallel_mode self.cover_stdlib = cover_stdlib self.exclude_re = "" self.exclude_list = [] @@ -24,8 +37,19 @@ class coverage: self.sysprefix = self.file_locator.abs_file(sys.prefix) self.collector = Collector(self._should_trace) - self.data = CoverageData(collector="coverage v%s" % __version__) - + + # Create the data file. + if data_suffix: + if not isinstance(data_suffix, basestring): + # if data_suffix=True, use .machinename.pid + data_suffix = ".%s.%s" % (socket.gethostname(), os.getpid()) + else: + data_suffix = None + + self.data = CoverageData( + basename=data_file, suffix=data_suffix, + collector="coverage v%s" % __version__) + # The default exclude pattern. self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]') @@ -79,19 +103,25 @@ class coverage: def get_ready(self): self.collector.reset() - if self.parallel_mode: - self.data.set_suffix("%s.%s" % (socket.gethostname(), os.getpid())) self.data.read() def start(self): + """Start measuring code coverage.""" self.get_ready() self.collector.start() def stop(self): + """Stop measuring code coverage.""" self.collector.stop() self._harvest_data() def erase(self): + """Erase previously-collected coverage data. + + This removes the in-memory data collected in this session as well as + discarding the data file. + + """ self.get_ready() self.collector.reset() self.data.erase() @@ -118,6 +148,7 @@ class coverage: return self.exclude_list def save(self): + """Save the collected coverage data to the data file.""" self._harvest_data() self.data.write() diff --git a/coverage/data.py b/coverage/data.py index 1d5c5073..00d5b309 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -21,17 +21,24 @@ class CoverageData: # Environment variable naming the data file. filename_env = "COVERAGE_FILE" - def __init__(self, collector=None): + def __init__(self, basename=None, suffix=None, collector=None): """Create a CoverageData. - `collector` is a string describing the coverage measurement software. + `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.basename = basename self.collector = collector + self.suffix = suffix self.use_file = True self.filename = None - self.suffix = None # A map from canonical Python source file name to a dictionary in # which there's an entry for each line number that has been @@ -48,23 +55,15 @@ class CoverageData: """Set whether or not to use a disk file for data.""" self.use_file = use_file - def set_suffix(self, suffix): - """Set a suffix to use for the data file name. - - This can be used for multiple or parallel execution, so that many - coverage data files can exist simultaneously. - - """ - 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( - self.filename_env, self.filename_default) + self.filename = (self.basename or + os.environ.get(self.filename_env, self.filename_default)) + if self.suffix: - self.filename += "." + self.suffix + self.filename += self.suffix def read(self): """Read coverage data from the coverage data file (if it exists).""" diff --git a/test/test_api.py b/test/test_api.py index f16c35dd..f4c48f4d 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -195,3 +195,48 @@ class ApiTest(CoverageTest): self.assertEqual(cov.exclude_re, "(foo)|(bar)") cov.clear_exclude() self.assertEqual(cov.get_exclude_list(), []) + + def testDatafileDefault(self): + # Default data file behavior: it's .coverage + self.makeFile("datatest1.py", """\ + fooey = 17 + """) + + self.assert_equal_sets(os.listdir("."), ["datatest1.py"]) + cov = coverage.coverage() + cov.start() + self.importModule("datatest1") + cov.stop() + cov.save() + self.assert_equal_sets(os.listdir("."), + ["datatest1.py", "datatest1.pyc", ".coverage"]) + + def testDatafileSpecified(self): + # You can specify the data file name. + self.makeFile("datatest2.py", """\ + fooey = 17 + """) + + self.assert_equal_sets(os.listdir("."), ["datatest2.py"]) + cov = coverage.coverage(datafile="cov.data") + cov.start() + self.importModule("datatest2") + cov.stop() + cov.save() + self.assert_equal_sets(os.listdir("."), + ["datatest2.py", "datatest2.pyc", "cov.data"]) + + def testDatafileSpecified(self): + # You can specify the data file name and suffix. + self.makeFile("datatest3.py", """\ + fooey = 17 + """) + + self.assert_equal_sets(os.listdir("."), ["datatest3.py"]) + cov = coverage.coverage(data_file="cov.data", data_suffix=".14") + cov.start() + self.importModule("datatest3") + cov.stop() + cov.save() + self.assert_equal_sets(os.listdir("."), + ["datatest3.py", "datatest3.pyc", "cov.data.14"]) diff --git a/test/test_data.py b/test/test_data.py index 7a2687fd..44c123fe 100644 --- a/test/test_data.py +++ b/test/test_data.py @@ -48,13 +48,11 @@ class DataTest(CoverageTest): self.assert_summary(covdata2, SUMMARY_1) def test_combining(self): - covdata1 = CoverageData() - covdata1.set_suffix('1') + covdata1 = CoverageData(suffix='1') covdata1.add_line_data(DATA_1) covdata1.write() - covdata2 = CoverageData() - covdata2.set_suffix('2') + covdata2 = CoverageData(suffix='2') covdata2.add_line_data(DATA_2) covdata2.write() |