| Index: tools/telemetry/third_party/coverage/coverage/plugin_support.py
|
| diff --git a/tools/telemetry/third_party/coverage/coverage/plugin_support.py b/tools/telemetry/third_party/coverage/coverage/plugin_support.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f88342e9918cac8dbea5af65103890e07d41d5ec
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/coverage/coverage/plugin_support.py
|
| @@ -0,0 +1,244 @@
|
| +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
| +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
|
| +
|
| +"""Support for plugins."""
|
| +
|
| +import os.path
|
| +import sys
|
| +
|
| +from coverage.misc import CoverageException
|
| +from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
|
| +
|
| +
|
| +class Plugins(object):
|
| + """The currently loaded collection of coverage.py plugins."""
|
| +
|
| + 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):
|
| + """Load plugins from `modules`.
|
| +
|
| + Returns a list of loaded and configured plugins.
|
| +
|
| + """
|
| + plugins = cls()
|
| + plugins.debug = debug
|
| +
|
| + for module in modules:
|
| + plugins.current_module = module
|
| + __import__(module)
|
| + mod = sys.modules[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)
|
| + coverage_init(plugins, options)
|
| +
|
| + plugins.current_module = None
|
| + return plugins
|
| +
|
| + def add_file_tracer(self, plugin):
|
| + """Add a file tracer plugin.
|
| +
|
| + `plugin` is an instance of a third-party plugin class. It 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.
|
| +
|
| + `plugin` is a :class:`CoveragePlugin` instance to add. `specialized`
|
| + is a list to append the plugin to.
|
| +
|
| + """
|
| + 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)
|
| +
|
| + def __nonzero__(self):
|
| + return bool(self.order)
|
| +
|
| + __bool__ = __nonzero__
|
| +
|
| + def __iter__(self):
|
| + return iter(self.order)
|
| +
|
| + def get(self, plugin_name):
|
| + """Return a plugin by name."""
|
| + return self.names[plugin_name]
|
| +
|
| +
|
| +class LabelledDebug(object):
|
| + """A Debug writer, but with labels for prepending to the messages."""
|
| +
|
| + def __init__(self, label, debug, prev_labels=()):
|
| + self.labels = list(prev_labels) + [label]
|
| + self.debug = debug
|
| +
|
| + def add_label(self, label):
|
| + """Add a label to the writer, and return a new `LabelledDebug`."""
|
| + return LabelledDebug(label, self.debug, self.labels)
|
| +
|
| + def message_prefix(self):
|
| + """The prefix to use on messages, combining the labels."""
|
| + prefixes = self.labels + ['']
|
| + return ":\n".join(" "*i+label for i, label in enumerate(prefixes))
|
| +
|
| + def write(self, message):
|
| + """Write `message`, but with the labels prepended."""
|
| + self.debug.write("%s%s" % (self.message_prefix(), message))
|
| +
|
| +
|
| +class DebugPluginWrapper(CoveragePlugin):
|
| + """Wrap a plugin, and use debug to report on what it's doing."""
|
| +
|
| + def __init__(self, plugin, debug):
|
| + super(DebugPluginWrapper, self).__init__()
|
| + self.plugin = plugin
|
| + self.debug = debug
|
| +
|
| + def file_tracer(self, filename):
|
| + tracer = self.plugin.file_tracer(filename)
|
| + self.debug.write("file_tracer(%r) --> %r" % (filename, tracer))
|
| + if tracer:
|
| + debug = self.debug.add_label("file %r" % (filename,))
|
| + tracer = DebugFileTracerWrapper(tracer, debug)
|
| + return tracer
|
| +
|
| + def file_reporter(self, filename):
|
| + reporter = self.plugin.file_reporter(filename)
|
| + self.debug.write("file_reporter(%r) --> %r" % (filename, reporter))
|
| + if reporter:
|
| + debug = self.debug.add_label("file %r" % (filename,))
|
| + reporter = DebugFileReporterWrapper(filename, reporter, debug)
|
| + return reporter
|
| +
|
| + def sys_info(self):
|
| + return self.plugin.sys_info()
|
| +
|
| +
|
| +class DebugFileTracerWrapper(FileTracer):
|
| + """A debugging `FileTracer`."""
|
| +
|
| + def __init__(self, tracer, debug):
|
| + self.tracer = tracer
|
| + self.debug = debug
|
| +
|
| + def _show_frame(self, frame):
|
| + """A short string identifying a frame, for debug messages."""
|
| + return "%s@%d" % (
|
| + os.path.basename(frame.f_code.co_filename),
|
| + frame.f_lineno,
|
| + )
|
| +
|
| + def source_filename(self):
|
| + sfilename = self.tracer.source_filename()
|
| + self.debug.write("source_filename() --> %r" % (sfilename,))
|
| + return sfilename
|
| +
|
| + def has_dynamic_source_filename(self):
|
| + has = self.tracer.has_dynamic_source_filename()
|
| + self.debug.write("has_dynamic_source_filename() --> %r" % (has,))
|
| + return has
|
| +
|
| + def dynamic_source_filename(self, filename, frame):
|
| + dyn = self.tracer.dynamic_source_filename(filename, frame)
|
| + self.debug.write("dynamic_source_filename(%r, %s) --> %r" % (
|
| + filename, self._show_frame(frame), dyn,
|
| + ))
|
| + return dyn
|
| +
|
| + def line_number_range(self, frame):
|
| + pair = self.tracer.line_number_range(frame)
|
| + self.debug.write("line_number_range(%s) --> %r" % (self._show_frame(frame), pair))
|
| + return pair
|
| +
|
| +
|
| +class DebugFileReporterWrapper(FileReporter):
|
| + """A debugging `FileReporter`."""
|
| +
|
| + def __init__(self, filename, reporter, debug):
|
| + super(DebugFileReporterWrapper, self).__init__(filename)
|
| + self.reporter = reporter
|
| + self.debug = debug
|
| +
|
| + def relative_filename(self):
|
| + ret = self.reporter.relative_filename()
|
| + self.debug.write("relative_filename() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def lines(self):
|
| + ret = self.reporter.lines()
|
| + self.debug.write("lines() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def excluded_lines(self):
|
| + ret = self.reporter.excluded_lines()
|
| + self.debug.write("excluded_lines() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def translate_lines(self, lines):
|
| + ret = self.reporter.translate_lines(lines)
|
| + self.debug.write("translate_lines(%r) --> %r" % (lines, ret))
|
| + return ret
|
| +
|
| + def translate_arcs(self, arcs):
|
| + ret = self.reporter.translate_arcs(arcs)
|
| + self.debug.write("translate_arcs(%r) --> %r" % (arcs, ret))
|
| + return ret
|
| +
|
| + def no_branch_lines(self):
|
| + ret = self.reporter.no_branch_lines()
|
| + self.debug.write("no_branch_lines() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def exit_counts(self):
|
| + ret = self.reporter.exit_counts()
|
| + self.debug.write("exit_counts() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def arcs(self):
|
| + ret = self.reporter.arcs()
|
| + self.debug.write("arcs() --> %r" % (ret,))
|
| + return ret
|
| +
|
| + def source(self):
|
| + ret = self.reporter.source()
|
| + self.debug.write("source() --> %d chars" % (len(ret),))
|
| + return ret
|
| +
|
| + def source_token_lines(self):
|
| + ret = list(self.reporter.source_token_lines())
|
| + self.debug.write("source_token_lines() --> %d tokens" % (len(ret),))
|
| + return ret
|
|
|