OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |