Home | History | Annotate | Download | only in coverage
      1 """Config file for coverage.py"""
      2 
      3 import os
      4 from coverage.backward import configparser          # pylint: disable=W0622
      5 
      6 # The default line exclusion regexes
      7 DEFAULT_EXCLUDE = [
      8     '(?i)# *pragma[: ]*no *cover',
      9     ]
     10 
     11 # The default partial branch regexes, to be modified by the user.
     12 DEFAULT_PARTIAL = [
     13     '(?i)# *pragma[: ]*no *branch',
     14     ]
     15 
     16 # The default partial branch regexes, based on Python semantics.
     17 # These are any Python branching constructs that can't actually execute all
     18 # their branches.
     19 DEFAULT_PARTIAL_ALWAYS = [
     20     'while (True|1|False|0):',
     21     'if (True|1|False|0):',
     22     ]
     23 
     24 
     25 class CoverageConfig(object):
     26     """Coverage.py configuration.
     27 
     28     The attributes of this class are the various settings that control the
     29     operation of coverage.py.
     30 
     31     """
     32 
     33     def __init__(self):
     34         """Initialize the configuration attributes to their defaults."""
     35         # Defaults for [run]
     36         self.branch = False
     37         self.cover_pylib = False
     38         self.data_file = ".coverage"
     39         self.parallel = False
     40         self.timid = False
     41         self.source = None
     42 
     43         # Defaults for [report]
     44         self.exclude_list = DEFAULT_EXCLUDE[:]
     45         self.ignore_errors = False
     46         self.include = None
     47         self.omit = None
     48         self.partial_list = DEFAULT_PARTIAL[:]
     49         self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:]
     50         self.precision = 0
     51 
     52         # Defaults for [html]
     53         self.html_dir = "htmlcov"
     54 
     55         # Defaults for [xml]
     56         self.xml_output = "coverage.xml"
     57 
     58         # Defaults for [paths]
     59         self.paths = {}
     60 
     61     def from_environment(self, env_var):
     62         """Read configuration from the `env_var` environment variable."""
     63         # Timidity: for nose users, read an environment variable.  This is a
     64         # cheap hack, since the rest of the command line arguments aren't
     65         # recognized, but it solves some users' problems.
     66         env = os.environ.get(env_var, '')
     67         if env:
     68             self.timid = ('--timid' in env)
     69 
     70     def from_args(self, **kwargs):
     71         """Read config values from `kwargs`."""
     72         for k, v in kwargs.items():
     73             if v is not None:
     74                 setattr(self, k, v)
     75 
     76     def from_file(self, *files):
     77         """Read configuration from .rc files.
     78 
     79         Each argument in `files` is a file name to read.
     80 
     81         """
     82         cp = configparser.RawConfigParser()
     83         cp.read(files)
     84 
     85         # [run]
     86         if cp.has_option('run', 'branch'):
     87             self.branch = cp.getboolean('run', 'branch')
     88         if cp.has_option('run', 'cover_pylib'):
     89             self.cover_pylib = cp.getboolean('run', 'cover_pylib')
     90         if cp.has_option('run', 'data_file'):
     91             self.data_file = cp.get('run', 'data_file')
     92         if cp.has_option('run', 'include'):
     93             self.include = self.get_list(cp, 'run', 'include')
     94         if cp.has_option('run', 'omit'):
     95             self.omit = self.get_list(cp, 'run', 'omit')
     96         if cp.has_option('run', 'parallel'):
     97             self.parallel = cp.getboolean('run', 'parallel')
     98         if cp.has_option('run', 'source'):
     99             self.source = self.get_list(cp, 'run', 'source')
    100         if cp.has_option('run', 'timid'):
    101             self.timid = cp.getboolean('run', 'timid')
    102 
    103         # [report]
    104         if cp.has_option('report', 'exclude_lines'):
    105             self.exclude_list = \
    106                 self.get_line_list(cp, 'report', 'exclude_lines')
    107         if cp.has_option('report', 'ignore_errors'):
    108             self.ignore_errors = cp.getboolean('report', 'ignore_errors')
    109         if cp.has_option('report', 'include'):
    110             self.include = self.get_list(cp, 'report', 'include')
    111         if cp.has_option('report', 'omit'):
    112             self.omit = self.get_list(cp, 'report', 'omit')
    113         if cp.has_option('report', 'partial_branches'):
    114             self.partial_list = \
    115                 self.get_line_list(cp, 'report', 'partial_branches')
    116         if cp.has_option('report', 'partial_branches_always'):
    117             self.partial_always_list = \
    118                 self.get_line_list(cp, 'report', 'partial_branches_always')
    119         if cp.has_option('report', 'precision'):
    120             self.precision = cp.getint('report', 'precision')
    121 
    122         # [html]
    123         if cp.has_option('html', 'directory'):
    124             self.html_dir = cp.get('html', 'directory')
    125 
    126         # [xml]
    127         if cp.has_option('xml', 'output'):
    128             self.xml_output = cp.get('xml', 'output')
    129 
    130         # [paths]
    131         if cp.has_section('paths'):
    132             for option in cp.options('paths'):
    133                 self.paths[option] = self.get_list(cp, 'paths', option)
    134 
    135     def get_list(self, cp, section, option):
    136         """Read a list of strings from the ConfigParser `cp`.
    137 
    138         The value of `section` and `option` is treated as a comma- and newline-
    139         separated list of strings.  Each value is stripped of whitespace.
    140 
    141         Returns the list of strings.
    142 
    143         """
    144         value_list = cp.get(section, option)
    145         values = []
    146         for value_line in value_list.split('\n'):
    147             for value in value_line.split(','):
    148                 value = value.strip()
    149                 if value:
    150                     values.append(value)
    151         return values
    152 
    153     def get_line_list(self, cp, section, option):
    154         """Read a list of full-line strings from the ConfigParser `cp`.
    155 
    156         The value of `section` and `option` is treated as a newline-separated
    157         list of strings.  Each value is stripped of whitespace.
    158 
    159         Returns the list of strings.
    160 
    161         """
    162         value_list = cp.get(section, option)
    163         return list(filter(None, value_list.split('\n')))
    164 
    165