diff options
Diffstat (limited to 'coverage/config.py')
-rw-r--r-- | coverage/config.py | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/coverage/config.py b/coverage/config.py index 7b142671..9939d6c0 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -1,22 +1,21 @@ -"""Config file for coverage.py""" +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt -import os, re, sys -from coverage.backward import string_class, iitems -from coverage.misc import CoverageException +"""Config file for coverage.py""" +import collections +import os +import re +import sys -# In py3, ConfigParser was renamed to the more-standard configparser -try: - import configparser -except ImportError: - import ConfigParser as configparser +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): - # pylint: disable=super-init-not-called configparser.RawConfigParser.__init__(self) self.section_prefix = section_prefix @@ -61,7 +60,7 @@ class HandyConfigParser(configparser.RawConfigParser): 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) + word = next(w for w in m.groups() if w is not None) # pragma: part covered if word == "$": return "$" else: @@ -112,10 +111,8 @@ class HandyConfigParser(configparser.RawConfigParser): re.compile(value) except re.error as e: raise CoverageException( - "Invalid [%s].%s value %r: %s" % ( - section, option, value, e - ) - ) + "Invalid [%s].%s value %r: %s" % (section, option, value, e) + ) if value: value_list.append(value) return value_list @@ -124,12 +121,12 @@ class HandyConfigParser(configparser.RawConfigParser): # 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 @@ -137,7 +134,7 @@ DEFAULT_PARTIAL = [ DEFAULT_PARTIAL_ALWAYS = [ 'while (True|1|False|0):', 'if (True|1|False|0):', - ] +] class CoverageConfig(object): @@ -158,11 +155,12 @@ class CoverageConfig(object): self.concurrency = None self.cover_pylib = False self.data_file = ".coverage" - self.parallel = False - self.timid = False - self.source = None self.debug = [] + self.note = None + self.parallel = False self.plugins = [] + self.source = None + self.timid = False # Defaults for [report] self.exclude_list = DEFAULT_EXCLUDE[:] @@ -170,15 +168,15 @@ class CoverageConfig(object): self.ignore_errors = False self.include = None self.omit = None - self.partial_list = DEFAULT_PARTIAL[:] 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.html_dir = "htmlcov" self.extra_css = None + self.html_dir = "htmlcov" self.html_title = "Coverage report" # Defaults for [xml] @@ -215,9 +213,7 @@ class CoverageConfig(object): try: files_read = cp.read(filename) except configparser.Error as err: - raise CoverageException( - "Couldn't read config file %s: %s" % (filename, err) - ) + raise CoverageException("Couldn't read config file %s: %s" % (filename, err)) if not files_read: return False @@ -227,9 +223,24 @@ class CoverageConfig(object): 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) - ) + 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'): @@ -258,10 +269,11 @@ class CoverageConfig(object): ('cover_pylib', 'run:cover_pylib', 'boolean'), ('data_file', 'run:data_file'), ('debug', 'run:debug', 'list'), - ('plugins', 'run:plugins', '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'), @@ -271,27 +283,27 @@ class CoverageConfig(object): ('ignore_errors', 'report:ignore_errors', 'boolean'), ('include', 'report:include', 'list'), ('omit', 'report:omit', 'list'), - ('partial_list', 'report:partial_branches', 'regexlist'), ('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] - ('html_dir', 'html:directory'), ('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_) + method = getattr(cp, 'get' + type_) setattr(self, attr, method(section, option)) def get_plugin_options(self, plugin): |