summaryrefslogtreecommitdiff
path: root/coverage/control.py
diff options
context:
space:
mode:
authorJustas Sadzevičius <justas.sadzevicius@gmail.com>2019-04-21 06:02:09 +0300
committerNed Batchelder <ned@nedbatchelder.com>2019-04-20 23:02:09 -0400
commit4a5ad41f106d6d9fff97e10cae3571b7b67823d5 (patch)
tree1c1555ea6cb2c86f15dc528ce65d0e34e62e4e32 /coverage/control.py
parenta92f0023e015a82f8c875e7a90210e22aaf0174b (diff)
downloadpython-coveragepy-git-4a5ad41f106d6d9fff97e10cae3571b7b67823d5.tar.gz
Plugin support for dynamic context (#783)
* Introduce a new plugin type: dynamic context labels. * Test dynamic context plugins * Helper method to get full paths to measured files * Get correct filenames on all OS * Improve wording
Diffstat (limited to 'coverage/control.py')
-rw-r--r--coverage/control.py39
1 files changed, 37 insertions, 2 deletions
diff --git a/coverage/control.py b/coverage/control.py
index ea6698d4..ae5f0442 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -335,6 +335,34 @@ class Coverage(object):
if not should_skip:
self._data.read()
+ def _combine_context_switchers(self, context_switchers):
+ """Create a single context switcher from multiple switchers.
+
+ `context_switchers` is a list of methods that take a frame
+ as an argument and return a string to use as the new context label.
+
+ Returns a method that composits `context_switchers` methods, or None
+ if `context_switchers` is an empty list.
+
+ When invoked, the combined switcher calls `context_switchers` one-by-one
+ until a string is returned. Combined switcher returns None if all
+ `context_switchers` return None.
+ """
+ if not context_switchers:
+ return None
+
+ if len(context_switchers) == 1:
+ return context_switchers[0]
+
+ def should_start_context(frame):
+ for switcher in context_switchers:
+ new_context = switcher(frame)
+ if new_context is not None:
+ return new_context
+ return None
+
+ return should_start_context
+
def _init_for_start(self):
"""Initialization for start()"""
# Construct the collector.
@@ -350,14 +378,21 @@ class Coverage(object):
self.config.parallel = True
if self.config.dynamic_context is None:
- should_start_context = None
+ context_switchers = []
elif self.config.dynamic_context == "test_function":
- should_start_context = should_start_context_test_function
+ context_switchers = [should_start_context_test_function]
else:
raise CoverageException(
"Don't understand dynamic_context setting: {!r}".format(self.config.dynamic_context)
)
+ context_switchers.extend([
+ plugin.dynamic_context
+ for plugin in self._plugins.context_switchers
+ ])
+
+ should_start_context = self._combine_context_switchers(context_switchers)
+
self._collector = Collector(
should_trace=self._should_trace,
check_include=self._check_include_omit_etc,