summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2019-06-23 07:14:16 -0400
committerNed Batchelder <ned@nedbatchelder.com>2019-06-25 09:54:41 -0400
commite9e703c7885840412295a0aaf3c84b5244483881 (patch)
treeab63e85a914e00207b2e3ae0614c11ea766d7813
parente126d4720a4abad33a772734e0a0b40403b974d2 (diff)
downloadpython-coveragepy-git-e9e703c7885840412295a0aaf3c84b5244483881.tar.gz
New API: Coverage.current() returns the latest started instance.
-rw-r--r--CHANGES.rst2
-rw-r--r--coverage/control.py15
-rw-r--r--tests/test_api.py31
3 files changed, 48 insertions, 0 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 3e651d2e..3e9de91e 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -32,6 +32,8 @@ Unreleased
information to each covered line. Hovering over the "ctx" marker at the
end of the line reveals a list of the contexts that covered the line.
+- Added :meth:`Coverage.current` to get the latest started `Coverage` instance.
+
- Error handling during reporting has changed slightly. All reporting methods
now behave the same. The ``--ignore-errors`` option keeps errors from
stopping the reporting, but files that couldn't parse as Python will always
diff --git a/coverage/control.py b/coverage/control.py
index c398f2a7..03e36324 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -55,6 +55,17 @@ class Coverage(object):
"""
+ # The stack of started Coverage instances.
+ _instances = []
+
+ @classmethod
+ def current(cls):
+ """Get the latest started `Coverage` instance, if any."""
+ if cls._instances:
+ return cls._instances[-1]
+ else:
+ return None
+
def __init__(
self, data_file=None, data_suffix=None, cover_pylib=None,
auto_data=False, timid=None, branch=None, config_file=True,
@@ -453,9 +464,13 @@ class Coverage(object):
self._collector.start()
self._started = True
+ self._instances.append(self)
def stop(self):
"""Stop measuring code coverage."""
+ if self._instances:
+ if self._instances[-1] is self:
+ self._instances.pop()
if self._started:
self._collector.stop()
self._started = False
diff --git a/tests/test_api.py b/tests/test_api.py
index a034c828..920cd9ad 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -614,6 +614,37 @@ class ApiTest(CoverageTest):
cov.switch_context("test3")
+class CurrentInstanceTest(CoverageTest):
+ """Tests of Coverage.current()."""
+
+ def assert_current_is_none(self, current):
+ """Assert that a current we expect to be None is correct."""
+ # During meta-coverage, the None answers will be wrong because the
+ # overall coverage measurement will still be on the current-stack.
+ # Since we know they will be wrong, and we have non-meta test runs
+ # also, don't assert them.
+ if not env.METACOV:
+ assert current is None
+
+ def test_current(self):
+ cur0 = coverage.Coverage.current()
+ self.assert_current_is_none(cur0)
+ # Making an instance doesn't make it current.
+ cov = coverage.Coverage()
+ cur1 = coverage.Coverage.current()
+ self.assert_current_is_none(cur1)
+ assert cur0 is cur1
+ # Starting the instance makes it current.
+ cov.start()
+ cur2 = coverage.Coverage.current()
+ assert cur2 is cov
+ # Stopping the instance makes current None again.
+ cov.stop()
+ cur3 = coverage.Coverage.current()
+ self.assert_current_is_none(cur3)
+ assert cur0 is cur3
+
+
class NamespaceModuleTest(UsingModulesMixin, CoverageTest):
"""Test PEP-420 namespace modules."""