diff options
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/control.py | 23 | ||||
-rw-r--r-- | coverage/misc.py | 23 | ||||
-rw-r--r-- | coverage/plugin_support.py | 70 |
3 files changed, 65 insertions, 51 deletions
diff --git a/coverage/control.py b/coverage/control.py index e4e67d3a..1dbf0672 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -21,9 +21,9 @@ from coverage.files import PathAliases, find_python_files, prep_patterns from coverage.files import ModuleMatcher, abs_file from coverage.html import HtmlReporter from coverage.misc import CoverageException, bool_or_none, join_regex -from coverage.misc import file_be_gone, overrides +from coverage.misc import file_be_gone from coverage.monkey import patch_multiprocessing -from coverage.plugin import CoveragePlugin, FileReporter +from coverage.plugin import FileReporter from coverage.plugin_support import Plugins from coverage.python import PythonFileReporter from coverage.results import Analysis, Numbers @@ -172,7 +172,7 @@ class Coverage(object): self.omit = self.include = self.source = None self.source_pkgs = None self.data = self.collector = None - self.plugins = self.file_tracing_plugins = None + self.plugins = None self.pylib_dirs = self.cover_dirs = None self.data_suffix = self.run_suffix = None self._exclude_re = None @@ -207,11 +207,6 @@ class Coverage(object): # Load plugins self.plugins = Plugins.load_plugins(self.config.plugins, self.config, self.debug) - self.file_tracing_plugins = [] - for plugin in self.plugins: - if overrides(plugin, "file_tracer", CoveragePlugin): - self.file_tracing_plugins.append(plugin) - # _exclude_re is a dict that maps exclusion list names to compiled # regexes. self._exclude_re = {} @@ -246,17 +241,17 @@ class Coverage(object): ) # Early warning if we aren't going to be able to support plugins. - if self.file_tracing_plugins and not self.collector.supports_plugins: + if self.plugins.file_tracers and not self.collector.supports_plugins: self._warn( "Plugin file tracers (%s) aren't supported with %s" % ( ", ".join( plugin._coverage_plugin_name - for plugin in self.file_tracing_plugins + for plugin in self.plugins.file_tracers ), self.collector.tracer_name(), ) ) - for plugin in self.file_tracing_plugins: + for plugin in self.plugins.file_tracers: plugin._coverage_enabled = False # Suffixes are a bit tricky. We want to use the data suffix only when @@ -482,7 +477,7 @@ class Coverage(object): # Try the plugins, see if they have an opinion about the file. plugin = None - for plugin in self.file_tracing_plugins: + for plugin in self.plugins.file_tracers: if not plugin._coverage_enabled: continue @@ -1037,7 +1032,7 @@ class Coverage(object): implementation = "unknown" ft_plugins = [] - for ft in self.file_tracing_plugins: + for ft in self.plugins.file_tracers: ft_name = ft._coverage_plugin_name if not ft._coverage_enabled: ft_name += " (disabled)" @@ -1049,7 +1044,7 @@ class Coverage(object): ('cover_dirs', self.cover_dirs), ('pylib_dirs', self.pylib_dirs), ('tracer', self.collector.tracer_name()), - ('file_tracing_plugins', ft_plugins), + ('plugins.file_tracers', ft_plugins), ('config_files', self.config.attempted_config_files), ('configs_read', self.config.config_files), ('data_path', self.data.filename), diff --git a/coverage/misc.py b/coverage/misc.py index 0dad0559..21b7333c 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -158,29 +158,6 @@ class Hasher(object): return self.md5.hexdigest() -def overrides(obj, method_name, base_class): - """Does `obj` override the `method_name` it got from `base_class`? - - Determine if `obj` implements the method called `method_name`, which it - inherited from `base_class`. - - Returns a boolean. - - """ - klass = obj.__class__ - klass_func = getattr(klass, method_name) - base_func = getattr(base_class, method_name) - - # Python 2/3 compatibility: Python 2 returns an instancemethod object, the - # function is the .im_func attribute. Python 3 returns a plain function - # object already. - if env.PY2: - klass_func = klass_func.im_func - base_func = base_func.im_func - - return klass_func is not base_func - - # TODO: abc? def _needs_to_implement(that, func_name): """Helper to raise NotImplementedError in interface stubs.""" diff --git a/coverage/plugin_support.py b/coverage/plugin_support.py index 4f22c137..ae72f797 100644 --- a/coverage/plugin_support.py +++ b/coverage/plugin_support.py @@ -13,6 +13,10 @@ class Plugins(object): def __init__(self): self.order = [] self.names = {} + self.file_tracers = [] + + self.current_module = None + self.debug = None @classmethod def load_plugins(cls, modules, config, debug=None): @@ -22,30 +26,68 @@ class Plugins(object): """ plugins = cls() + plugins.debug = debug for module in modules: + plugins.current_module = module __import__(module) mod = sys.modules[module] - plugin_class = getattr(mod, "Plugin", None) - if not plugin_class: - raise CoverageException("Plugin module %r didn't define a Plugin class" % module) + coverage_init = getattr(mod, "coverage_init", None) + if not coverage_init: + raise CoverageException( + "Plugin module %r didn't define a coverage_init function" % module + ) options = config.get_plugin_options(module) - plugin = plugin_class(options) - if debug and debug.should('plugin'): - debug.write("Loaded plugin %r: %r" % (module, plugin)) - labelled = LabelledDebug("plugin %r" % (module,), debug) - plugin = DebugPluginWrapper(plugin, labelled) - - # pylint: disable=attribute-defined-outside-init - plugin._coverage_plugin_name = module - plugin._coverage_enabled = True - plugins.order.append(plugin) - plugins.names[module] = plugin + coverage_init(plugins, options) + plugins.current_module = None return plugins + def add_file_tracer(self, plugin): + """Add a file tracer plugin. + + ``plugin`` must implement the :meth:`CoveragePlugin.file_tracer` method. + + """ + self._add_plugin(plugin, self.file_tracers) + + def add_noop(self, plugin): + """Add a plugin that does nothing. + + This is only useful for testing the plugin support. + + """ + self._add_plugin(plugin, None) + + def _add_plugin(self, plugin, specialized): + """Add a plugin object. + + Arguments: + plugin (CoveragePlugin): the plugin to add. + + specialized (list): the list of plugins to add this to. + + Returns: + plugin: may be a different object than passed in. + + """ + plugin_name = "%s.%s" % (self.current_module, plugin.__class__.__name__) + if self.debug and self.debug.should('plugin'): + self.debug.write("Loaded plugin %r: %r" % (self.current_module, plugin)) + labelled = LabelledDebug("plugin %r" % (self.current_module,), self.debug) + plugin = DebugPluginWrapper(plugin, labelled) + + # pylint: disable=attribute-defined-outside-init + plugin._coverage_plugin_name = plugin_name + plugin._coverage_enabled = True + self.order.append(plugin) + self.names[plugin_name] = plugin + if specialized is not None: + specialized.append(plugin) + return plugin + def __nonzero__(self): return bool(self.order) |