summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2014-08-21 10:35:15 -0400
committerNed Batchelder <ned@nedbatchelder.com>2014-08-21 10:35:15 -0400
commit44238cb66d14a6fb2f4d30f1cef9fdf0bb5f2e2d (patch)
tree4f9ef805140a7f18430d7e5bf8d1a47efca41698 /coverage
parentcb17b350caf9e113b7a3a36c5add5d16a88ea46d (diff)
downloadpython-coveragepy-git-44238cb66d14a6fb2f4d30f1cef9fdf0bb5f2e2d.tar.gz
More-serious plugin support
Diffstat (limited to 'coverage')
-rw-r--r--coverage/config.py25
-rw-r--r--coverage/control.py12
-rw-r--r--coverage/plugin.py36
3 files changed, 51 insertions, 22 deletions
diff --git a/coverage/config.py b/coverage/config.py
index 1826e5c2..c671ef75 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -37,6 +37,13 @@ class HandyConfigParser(configparser.RawConfigParser):
section = self.section_prefix + section
return configparser.RawConfigParser.options(self, section)
+ def get_section(self, section):
+ """Get the contents of a section, as a dictionary."""
+ d = {}
+ for opt in self.options(section):
+ d[opt] = self.get(section, opt)
+ return d
+
def get(self, section, *args, **kwargs):
"""Get a value, replacing environment variables also.
@@ -163,6 +170,9 @@ class CoverageConfig(object):
# Defaults for [paths]
self.paths = {}
+ # Options for plugins
+ self.plugin_options = {}
+
def from_environment(self, env_var):
"""Read configuration from the `env_var` environment variable."""
# Timidity: for nose users, read an environment variable. This is a
@@ -200,17 +210,22 @@ class CoverageConfig(object):
self.config_files.extend(files_read)
for option_spec in self.CONFIG_FILE_OPTIONS:
- self.set_attr_from_config_option(cp, *option_spec)
+ self._set_attr_from_config_option(cp, *option_spec)
# [paths] is special
if cp.has_section('paths'):
for option in cp.options('paths'):
self.paths[option] = cp.getlist('paths', option)
+ # plugins can have options
+ for plugin in self.plugins:
+ if cp.has_section(plugin):
+ self.plugin_options[plugin] = cp.get_section(plugin)
+
return True
CONFIG_FILE_OPTIONS = [
- # These are *args for set_attr_from_config_option:
+ # These are *args for _set_attr_from_config_option:
# (attr, where, type_="")
#
# attr is the attribute to set on the CoverageConfig object.
@@ -250,9 +265,13 @@ class CoverageConfig(object):
('xml_output', 'xml:output'),
]
- def set_attr_from_config_option(self, cp, attr, where, type_=''):
+ def _set_attr_from_config_option(self, cp, attr, where, type_=''):
"""Set an attribute on self if it exists in the ConfigParser."""
section, option = where.split(":")
if cp.has_option(section, option):
method = getattr(cp, 'get'+type_)
setattr(self, attr, method(section, option))
+
+ def get_plugin_options(self, plugin):
+ """Get a dictionary of options for the plugin named `plugin`."""
+ return self.plugin_options.get(plugin, {})
diff --git a/coverage/control.py b/coverage/control.py
index deb4e00f..6d232e5b 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -135,8 +135,8 @@ class Coverage(object):
self.debug = DebugControl(self.config.debug, debug_file or sys.stderr)
# Load plugins
- tracer_classes = load_plugins(self.config.plugins, "tracer")
- self.tracer_plugins = [cls() for cls in tracer_classes]
+ plugins = load_plugins(self.config.plugins, self.config)
+ self.tracer_plugins = []#[cls() for cls in tracer_classes]
self.auto_data = auto_data
@@ -282,10 +282,10 @@ class Coverage(object):
# Try the plugins, see if they have an opinion about the file.
for tracer in self.tracer_plugins:
- ext_disp = tracer.should_trace(canonical)
- if ext_disp:
- ext_disp.extension = tracer
- return ext_disp
+ plugin_disp = tracer.should_trace(canonical)
+ if plugin_disp:
+ plugin_disp.plugin = tracer
+ return plugin_disp
# If the user specified source or include, then that's authoritative
# about the outer bound of what to measure and we don't have to apply
diff --git a/coverage/plugin.py b/coverage/plugin.py
index 0b557106..8e26ae6b 100644
--- a/coverage/plugin.py
+++ b/coverage/plugin.py
@@ -1,20 +1,30 @@
"""Plugin management for coverage.py"""
-def load_plugins(modules, name):
- """Load plugins from `modules`, finding them by `name`.
+import sys
- Yields the loaded plugins.
+
+class CoveragePlugin(object):
+ """Base class for coverage.py plugins."""
+ def __init__(self, options):
+ self.options = options
+
+
+def load_plugins(modules, config):
+ """Load plugins from `modules`.
+
+ Returns a list of loaded and configured plugins.
"""
+ plugins = []
for module in modules:
- try:
- __import__(module)
- mod = sys.modules[module]
- except ImportError:
- blah()
- continue
-
- entry = getattr(mod, name, None)
- if entry:
- yield entry
+ __import__(module)
+ mod = sys.modules[module]
+
+ plugin_class = getattr(mod, "Plugin", None)
+ if plugin_class:
+ options = config.get_plugin_options(module)
+ plugin = plugin_class(options)
+ plugins.append(plugin)
+
+ return plugins