Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: tools/telemetry/third_party/coverage/coverage/config.py

Issue 1366913004: Add coverage Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/coverage/coverage/config.py
diff --git a/tools/telemetry/third_party/coverage/coverage/config.py b/tools/telemetry/third_party/coverage/coverage/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..458d490353530fe1e107b286183062730fa68afa
--- /dev/null
+++ b/tools/telemetry/third_party/coverage/coverage/config.py
@@ -0,0 +1,363 @@
+# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
+
+"""Config file for coverage.py"""
+
+import collections
+import os
+import re
+import sys
+
+from coverage.backward import configparser, iitems, string_class
+from coverage.misc import CoverageException
+
+
+class HandyConfigParser(configparser.RawConfigParser):
+ """Our specialization of ConfigParser."""
+
+ def __init__(self, section_prefix):
+ configparser.RawConfigParser.__init__(self)
+ self.section_prefix = section_prefix
+
+ def read(self, filename):
+ """Read a file name as UTF-8 configuration data."""
+ kwargs = {}
+ if sys.version_info >= (3, 2):
+ kwargs['encoding'] = "utf-8"
+ return configparser.RawConfigParser.read(self, filename, **kwargs)
+
+ def has_option(self, section, option):
+ section = self.section_prefix + section
+ return configparser.RawConfigParser.has_option(self, section, option)
+
+ def has_section(self, section):
+ section = self.section_prefix + section
+ return configparser.RawConfigParser.has_section(self, section)
+
+ def options(self, section):
+ 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.
+
+ The arguments are the same as `RawConfigParser.get`, but in the found
+ value, ``$WORD`` or ``${WORD}`` are replaced by the value of the
+ environment variable ``WORD``.
+
+ Returns the finished value.
+
+ """
+ section = self.section_prefix + section
+ v = configparser.RawConfigParser.get(self, section, *args, **kwargs)
+ def dollar_replace(m):
+ """Called for each $replacement."""
+ # Only one of the groups will have matched, just get its text.
+ word = next(w for w in m.groups() if w is not None) # pragma: part covered
+ if word == "$":
+ return "$"
+ else:
+ return os.environ.get(word, '')
+
+ dollar_pattern = r"""(?x) # Use extended regex syntax
+ \$(?: # A dollar sign, then
+ (?P<v1>\w+) | # a plain word,
+ {(?P<v2>\w+)} | # or a {-wrapped word,
+ (?P<char>[$]) # or a dollar sign.
+ )
+ """
+ v = re.sub(dollar_pattern, dollar_replace, v)
+ return v
+
+ def getlist(self, section, option):
+ """Read a list of strings.
+
+ The value of `section` and `option` is treated as a comma- and newline-
+ separated list of strings. Each value is stripped of whitespace.
+
+ Returns the list of strings.
+
+ """
+ value_list = self.get(section, option)
+ values = []
+ for value_line in value_list.split('\n'):
+ for value in value_line.split(','):
+ value = value.strip()
+ if value:
+ values.append(value)
+ return values
+
+ def getregexlist(self, section, option):
+ """Read a list of full-line regexes.
+
+ The value of `section` and `option` is treated as a newline-separated
+ list of regexes. Each value is stripped of whitespace.
+
+ Returns the list of strings.
+
+ """
+ line_list = self.get(section, option)
+ value_list = []
+ for value in line_list.splitlines():
+ value = value.strip()
+ try:
+ re.compile(value)
+ except re.error as e:
+ raise CoverageException(
+ "Invalid [%s].%s value %r: %s" % (section, option, value, e)
+ )
+ if value:
+ value_list.append(value)
+ return value_list
+
+
+# The default line exclusion regexes.
+DEFAULT_EXCLUDE = [
+ r'(?i)#\s*pragma[:\s]?\s*no\s*cover',
+]
+
+# The default partial branch regexes, to be modified by the user.
+DEFAULT_PARTIAL = [
+ r'(?i)#\s*pragma[:\s]?\s*no\s*branch',
+]
+
+# The default partial branch regexes, based on Python semantics.
+# These are any Python branching constructs that can't actually execute all
+# their branches.
+DEFAULT_PARTIAL_ALWAYS = [
+ 'while (True|1|False|0):',
+ 'if (True|1|False|0):',
+]
+
+
+class CoverageConfig(object):
+ """Coverage.py configuration.
+
+ The attributes of this class are the various settings that control the
+ operation of coverage.py.
+
+ """
+ def __init__(self):
+ """Initialize the configuration attributes to their defaults."""
+ # Metadata about the config.
+ self.attempted_config_files = []
+ self.config_files = []
+
+ # Defaults for [run]
+ self.branch = False
+ self.concurrency = None
+ self.cover_pylib = False
+ self.data_file = ".coverage"
+ self.debug = []
+ self.note = None
+ self.parallel = False
+ self.plugins = []
+ self.source = None
+ self.timid = False
+
+ # Defaults for [report]
+ self.exclude_list = DEFAULT_EXCLUDE[:]
+ self.fail_under = 0
+ self.ignore_errors = False
+ self.include = None
+ self.omit = None
+ self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:]
+ self.partial_list = DEFAULT_PARTIAL[:]
+ self.precision = 0
+ self.show_missing = False
+ self.skip_covered = False
+
+ # Defaults for [html]
+ self.extra_css = None
+ self.html_dir = "htmlcov"
+ self.html_title = "Coverage report"
+
+ # Defaults for [xml]
+ self.xml_output = "coverage.xml"
+ self.xml_package_depth = 99
+
+ # Defaults for [paths]
+ self.paths = {}
+
+ # Options for plugins
+ self.plugin_options = {}
+
+ MUST_BE_LIST = ["omit", "include", "debug", "plugins"]
+
+ def from_args(self, **kwargs):
+ """Read config values from `kwargs`."""
+ for k, v in iitems(kwargs):
+ if v is not None:
+ if k in self.MUST_BE_LIST and isinstance(v, string_class):
+ v = [v]
+ setattr(self, k, v)
+
+ def from_file(self, filename, section_prefix=""):
+ """Read configuration from a .rc file.
+
+ `filename` is a file name to read.
+
+ Returns True or False, whether the file could be read.
+
+ """
+ self.attempted_config_files.append(filename)
+
+ cp = HandyConfigParser(section_prefix)
+ try:
+ files_read = cp.read(filename)
+ except configparser.Error as err:
+ raise CoverageException("Couldn't read config file %s: %s" % (filename, err))
+ if not files_read:
+ return False
+
+ self.config_files.extend(files_read)
+
+ try:
+ for option_spec in self.CONFIG_FILE_OPTIONS:
+ self._set_attr_from_config_option(cp, *option_spec)
+ except ValueError as err:
+ raise CoverageException("Couldn't read config file %s: %s" % (filename, err))
+
+ # Check that there are no unrecognized options.
+ all_options = collections.defaultdict(set)
+ for option_spec in self.CONFIG_FILE_OPTIONS:
+ section, option = option_spec[1].split(":")
+ all_options[section].add(option)
+
+ for section, options in iitems(all_options):
+ if cp.has_section(section):
+ for unknown in set(cp.options(section)) - options:
+ if section_prefix:
+ section = section_prefix + section
+ raise CoverageException(
+ "Unrecognized option '[%s] %s=' in config file %s" % (
+ section, unknown, filename
+ )
+ )
+
+ # [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:
+ # (attr, where, type_="")
+ #
+ # attr is the attribute to set on the CoverageConfig object.
+ # where is the section:name to read from the configuration file.
+ # type_ is the optional type to apply, by using .getTYPE to read the
+ # configuration value from the file.
+
+ # [run]
+ ('branch', 'run:branch', 'boolean'),
+ ('concurrency', 'run:concurrency'),
+ ('cover_pylib', 'run:cover_pylib', 'boolean'),
+ ('data_file', 'run:data_file'),
+ ('debug', 'run:debug', 'list'),
+ ('include', 'run:include', 'list'),
+ ('note', 'run:note'),
+ ('omit', 'run:omit', 'list'),
+ ('parallel', 'run:parallel', 'boolean'),
+ ('plugins', 'run:plugins', 'list'),
+ ('source', 'run:source', 'list'),
+ ('timid', 'run:timid', 'boolean'),
+
+ # [report]
+ ('exclude_list', 'report:exclude_lines', 'regexlist'),
+ ('fail_under', 'report:fail_under', 'int'),
+ ('ignore_errors', 'report:ignore_errors', 'boolean'),
+ ('include', 'report:include', 'list'),
+ ('omit', 'report:omit', 'list'),
+ ('partial_always_list', 'report:partial_branches_always', 'regexlist'),
+ ('partial_list', 'report:partial_branches', 'regexlist'),
+ ('precision', 'report:precision', 'int'),
+ ('show_missing', 'report:show_missing', 'boolean'),
+ ('skip_covered', 'report:skip_covered', 'boolean'),
+
+ # [html]
+ ('extra_css', 'html:extra_css'),
+ ('html_dir', 'html:directory'),
+ ('html_title', 'html:title'),
+
+ # [xml]
+ ('xml_output', 'xml:output'),
+ ('xml_package_depth', 'xml:package_depth', 'int'),
+ ]
+
+ 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, {})
+
+ def set_option(self, option_name, value):
+ """Set an option in the configuration.
+
+ `option_name` is a colon-separated string indicating the section and
+ option name. For example, the ``branch`` option in the ``[run]``
+ section of the config file would be indicated with `"run:branch"`.
+
+ `value` is the new value for the option.
+
+ """
+
+ # Check all the hard-coded options.
+ for option_spec in self.CONFIG_FILE_OPTIONS:
+ attr, where = option_spec[:2]
+ if where == option_name:
+ setattr(self, attr, value)
+ return
+
+ # See if it's a plugin option.
+ plugin_name, _, key = option_name.partition(":")
+ if key and plugin_name in self.plugins:
+ self.plugin_options.setdefault(plugin_name, {})[key] = value
+ return
+
+ # If we get here, we didn't find the option.
+ raise CoverageException("No such option: %r" % option_name)
+
+ def get_option(self, option_name):
+ """Get an option from the configuration.
+
+ `option_name` is a colon-separated string indicating the section and
+ option name. For example, the ``branch`` option in the ``[run]``
+ section of the config file would be indicated with `"run:branch"`.
+
+ Returns the value of the option.
+
+ """
+
+ # Check all the hard-coded options.
+ for option_spec in self.CONFIG_FILE_OPTIONS:
+ attr, where = option_spec[:2]
+ if where == option_name:
+ return getattr(self, attr)
+
+ # See if it's a plugin option.
+ plugin_name, _, key = option_name.partition(":")
+ if key and plugin_name in self.plugins:
+ return self.plugin_options.get(plugin_name, {}).get(key)
+
+ # If we get here, we didn't find the option.
+ raise CoverageException("No such option: %r" % option_name)
« no previous file with comments | « tools/telemetry/third_party/coverage/coverage/collector.py ('k') | tools/telemetry/third_party/coverage/coverage/control.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698