summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-05-11 17:43:05 -0400
committerNed Batchelder <ned@nedbatchelder.com>2009-05-11 17:43:05 -0400
commit5288a2e51bc938dfcce206bb8ecffa9ac0c96871 (patch)
tree8dba3834ffee5a2a9ae9294c7c0172fbfee1e08b
parent8fbe22896bff70a8c72116eb222cd317f6db36d0 (diff)
downloadpython-coveragepy-git-5288a2e51bc938dfcce206bb8ecffa9ac0c96871.tar.gz
Re-think the api to set the data file name and suffix.
-rw-r--r--coverage/cmdline.py2
-rw-r--r--coverage/control.py43
-rw-r--r--coverage/data.py29
-rw-r--r--test/test_api.py45
-rw-r--r--test/test_data.py6
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()