|  | """Config file for coverage.py""" | 
|  |  | 
|  | import os | 
|  | from coverage.backward import configparser          # pylint: disable=W0622 | 
|  |  | 
|  | # The default line exclusion regexes | 
|  | DEFAULT_EXCLUDE = [ | 
|  | '(?i)# *pragma[: ]*no *cover', | 
|  | ] | 
|  |  | 
|  | # The default partial branch regexes, to be modified by the user. | 
|  | DEFAULT_PARTIAL = [ | 
|  | '(?i)# *pragma[: ]*no *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.""" | 
|  | # Defaults for [run] | 
|  | self.branch = False | 
|  | self.cover_pylib = False | 
|  | self.data_file = ".coverage" | 
|  | self.parallel = False | 
|  | self.timid = False | 
|  | self.source = None | 
|  |  | 
|  | # Defaults for [report] | 
|  | self.exclude_list = DEFAULT_EXCLUDE[:] | 
|  | self.ignore_errors = False | 
|  | self.include = None | 
|  | self.omit = None | 
|  | self.partial_list = DEFAULT_PARTIAL[:] | 
|  | self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:] | 
|  | self.precision = 0 | 
|  |  | 
|  | # Defaults for [html] | 
|  | self.html_dir = "htmlcov" | 
|  |  | 
|  | # Defaults for [xml] | 
|  | self.xml_output = "coverage.xml" | 
|  |  | 
|  | # Defaults for [paths] | 
|  | self.paths = {} | 
|  |  | 
|  | 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 | 
|  | # cheap hack, since the rest of the command line arguments aren't | 
|  | # recognized, but it solves some users' problems. | 
|  | env = os.environ.get(env_var, '') | 
|  | if env: | 
|  | self.timid = ('--timid' in env) | 
|  |  | 
|  | def from_args(self, **kwargs): | 
|  | """Read config values from `kwargs`.""" | 
|  | for k, v in kwargs.items(): | 
|  | if v is not None: | 
|  | setattr(self, k, v) | 
|  |  | 
|  | def from_file(self, *files): | 
|  | """Read configuration from .rc files. | 
|  |  | 
|  | Each argument in `files` is a file name to read. | 
|  |  | 
|  | """ | 
|  | cp = configparser.RawConfigParser() | 
|  | cp.read(files) | 
|  |  | 
|  | # [run] | 
|  | if cp.has_option('run', 'branch'): | 
|  | self.branch = cp.getboolean('run', 'branch') | 
|  | if cp.has_option('run', 'cover_pylib'): | 
|  | self.cover_pylib = cp.getboolean('run', 'cover_pylib') | 
|  | if cp.has_option('run', 'data_file'): | 
|  | self.data_file = cp.get('run', 'data_file') | 
|  | if cp.has_option('run', 'include'): | 
|  | self.include = self.get_list(cp, 'run', 'include') | 
|  | if cp.has_option('run', 'omit'): | 
|  | self.omit = self.get_list(cp, 'run', 'omit') | 
|  | if cp.has_option('run', 'parallel'): | 
|  | self.parallel = cp.getboolean('run', 'parallel') | 
|  | if cp.has_option('run', 'source'): | 
|  | self.source = self.get_list(cp, 'run', 'source') | 
|  | if cp.has_option('run', 'timid'): | 
|  | self.timid = cp.getboolean('run', 'timid') | 
|  |  | 
|  | # [report] | 
|  | if cp.has_option('report', 'exclude_lines'): | 
|  | self.exclude_list = \ | 
|  | self.get_line_list(cp, 'report', 'exclude_lines') | 
|  | if cp.has_option('report', 'ignore_errors'): | 
|  | self.ignore_errors = cp.getboolean('report', 'ignore_errors') | 
|  | if cp.has_option('report', 'include'): | 
|  | self.include = self.get_list(cp, 'report', 'include') | 
|  | if cp.has_option('report', 'omit'): | 
|  | self.omit = self.get_list(cp, 'report', 'omit') | 
|  | if cp.has_option('report', 'partial_branches'): | 
|  | self.partial_list = \ | 
|  | self.get_line_list(cp, 'report', 'partial_branches') | 
|  | if cp.has_option('report', 'partial_branches_always'): | 
|  | self.partial_always_list = \ | 
|  | self.get_line_list(cp, 'report', 'partial_branches_always') | 
|  | if cp.has_option('report', 'precision'): | 
|  | self.precision = cp.getint('report', 'precision') | 
|  |  | 
|  | # [html] | 
|  | if cp.has_option('html', 'directory'): | 
|  | self.html_dir = cp.get('html', 'directory') | 
|  |  | 
|  | # [xml] | 
|  | if cp.has_option('xml', 'output'): | 
|  | self.xml_output = cp.get('xml', 'output') | 
|  |  | 
|  | # [paths] | 
|  | if cp.has_section('paths'): | 
|  | for option in cp.options('paths'): | 
|  | self.paths[option] = self.get_list(cp, 'paths', option) | 
|  |  | 
|  | def get_list(self, cp, section, option): | 
|  | """Read a list of strings from the ConfigParser `cp`. | 
|  |  | 
|  | 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 = cp.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 get_line_list(self, cp, section, option): | 
|  | """Read a list of full-line strings from the ConfigParser `cp`. | 
|  |  | 
|  | The value of `section` and `option` is treated as a newline-separated | 
|  | list of strings.  Each value is stripped of whitespace. | 
|  |  | 
|  | Returns the list of strings. | 
|  |  | 
|  | """ | 
|  | value_list = cp.get(section, option) | 
|  | return list(filter(None, value_list.split('\n'))) | 
|  |  |