Sat, 04 Jul 2015 17:44:33 +0200
Prepared release of eric 6.0.7.
3495 | 1 | """Config file for coverage.py""" |
2 | ||
3 | import os, re, sys | |
4 | from .backward import string_class, iitems | |
5 | ||
6 | # In py3, # ConfigParser was renamed to the more-standard configparser | |
7 | try: | |
8 | import configparser # pylint: disable=F0401 | |
9 | except ImportError: | |
10 | import ConfigParser as configparser | |
11 | ||
12 | ||
13 | class HandyConfigParser(configparser.RawConfigParser): | |
14 | """Our specialization of ConfigParser.""" | |
15 | ||
16 | def read(self, filename): | |
17 | """Read a filename as UTF-8 configuration data.""" | |
18 | kwargs = {} | |
19 | if sys.version_info >= (3, 2): | |
20 | kwargs['encoding'] = "utf-8" | |
21 | return configparser.RawConfigParser.read(self, filename, **kwargs) | |
22 | ||
23 | def get(self, *args, **kwargs): | |
24 | v = configparser.RawConfigParser.get(self, *args, **kwargs) | |
25 | def dollar_replace(m): | |
26 | """Called for each $replacement.""" | |
27 | # Only one of the groups will have matched, just get its text. | |
28 | word = [w for w in m.groups() if w is not None][0] | |
29 | if word == "$": | |
30 | return "$" | |
31 | else: | |
32 | return os.environ.get(word, '') | |
33 | ||
34 | dollar_pattern = r"""(?x) # Use extended regex syntax | |
35 | \$(?: # A dollar sign, then | |
36 | (?P<v1>\w+) | # a plain word, | |
37 | {(?P<v2>\w+)} | # or a {-wrapped word, | |
38 | (?P<char>[$]) # or a dollar sign. | |
39 | ) | |
40 | """ | |
41 | v = re.sub(dollar_pattern, dollar_replace, v) | |
42 | return v | |
43 | ||
44 | def getlist(self, section, option): | |
45 | """Read a list of strings. | |
46 | ||
47 | The value of `section` and `option` is treated as a comma- and newline- | |
48 | separated list of strings. Each value is stripped of whitespace. | |
49 | ||
50 | Returns the list of strings. | |
51 | ||
52 | """ | |
53 | value_list = self.get(section, option) | |
54 | values = [] | |
55 | for value_line in value_list.split('\n'): | |
56 | for value in value_line.split(','): | |
57 | value = value.strip() | |
58 | if value: | |
59 | values.append(value) | |
60 | return values | |
61 | ||
62 | def getlinelist(self, section, option): | |
63 | """Read a list of full-line strings. | |
64 | ||
65 | The value of `section` and `option` is treated as a newline-separated | |
66 | list of strings. Each value is stripped of whitespace. | |
67 | ||
68 | Returns the list of strings. | |
69 | ||
70 | """ | |
71 | value_list = self.get(section, option) | |
72 | return list(filter(None, value_list.split('\n'))) | |
73 | ||
74 | ||
75 | # The default line exclusion regexes | |
76 | DEFAULT_EXCLUDE = [ | |
77 | '(?i)# *pragma[: ]*no *cover', | |
78 | ] | |
79 | ||
80 | # The default partial branch regexes, to be modified by the user. | |
81 | DEFAULT_PARTIAL = [ | |
82 | '(?i)# *pragma[: ]*no *branch', | |
83 | ] | |
84 | ||
85 | # The default partial branch regexes, based on Python semantics. | |
86 | # These are any Python branching constructs that can't actually execute all | |
87 | # their branches. | |
88 | DEFAULT_PARTIAL_ALWAYS = [ | |
89 | 'while (True|1|False|0):', | |
90 | 'if (True|1|False|0):', | |
91 | ] | |
92 | ||
93 | ||
94 | class CoverageConfig(object): | |
95 | """Coverage.py configuration. | |
96 | ||
97 | The attributes of this class are the various settings that control the | |
98 | operation of coverage.py. | |
99 | ||
100 | """ | |
101 | def __init__(self): | |
102 | """Initialize the configuration attributes to their defaults.""" | |
103 | # Metadata about the config. | |
104 | self.attempted_config_files = [] | |
105 | self.config_files = [] | |
106 | ||
107 | # Defaults for [run] | |
108 | self.branch = False | |
109 | self.cover_pylib = False | |
110 | self.data_file = ".coverage" | |
111 | self.parallel = False | |
112 | self.timid = False | |
113 | self.source = None | |
114 | self.debug = [] | |
115 | ||
116 | # Defaults for [report] | |
117 | self.exclude_list = DEFAULT_EXCLUDE[:] | |
118 | self.ignore_errors = False | |
119 | self.include = None | |
120 | self.omit = None | |
121 | self.partial_list = DEFAULT_PARTIAL[:] | |
122 | self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:] | |
123 | self.precision = 0 | |
124 | self.show_missing = False | |
125 | ||
126 | # Defaults for [html] | |
127 | self.html_dir = "htmlcov" | |
128 | self.extra_css = None | |
129 | self.html_title = "Coverage report" | |
130 | ||
131 | # Defaults for [xml] | |
132 | self.xml_output = "coverage.xml" | |
133 | ||
134 | # Defaults for [paths] | |
135 | self.paths = {} | |
136 | ||
137 | def from_environment(self, env_var): | |
138 | """Read configuration from the `env_var` environment variable.""" | |
139 | # Timidity: for nose users, read an environment variable. This is a | |
140 | # cheap hack, since the rest of the command line arguments aren't | |
141 | # recognized, but it solves some users' problems. | |
142 | env = os.environ.get(env_var, '') | |
143 | if env: | |
144 | self.timid = ('--timid' in env) | |
145 | ||
146 | MUST_BE_LIST = ["omit", "include", "debug"] | |
147 | ||
148 | def from_args(self, **kwargs): | |
149 | """Read config values from `kwargs`.""" | |
150 | for k, v in iitems(kwargs): | |
151 | if v is not None: | |
152 | if k in self.MUST_BE_LIST and isinstance(v, string_class): | |
153 | v = [v] | |
154 | setattr(self, k, v) | |
155 | ||
156 | def from_file(self, filename): | |
157 | """Read configuration from a .rc file. | |
158 | ||
159 | `filename` is a file name to read. | |
160 | ||
161 | """ | |
162 | self.attempted_config_files.append(filename) | |
163 | ||
164 | cp = HandyConfigParser() | |
165 | files_read = cp.read(filename) | |
166 | if files_read is not None: # return value changed in 2.4 | |
167 | self.config_files.extend(files_read) | |
168 | ||
169 | for option_spec in self.CONFIG_FILE_OPTIONS: | |
170 | self.set_attr_from_config_option(cp, *option_spec) | |
171 | ||
172 | # [paths] is special | |
173 | if cp.has_section('paths'): | |
174 | for option in cp.options('paths'): | |
175 | self.paths[option] = cp.getlist('paths', option) | |
176 | ||
177 | CONFIG_FILE_OPTIONS = [ | |
178 | # [run] | |
179 | ('branch', 'run:branch', 'boolean'), | |
180 | ('cover_pylib', 'run:cover_pylib', 'boolean'), | |
181 | ('data_file', 'run:data_file'), | |
182 | ('debug', 'run:debug', 'list'), | |
183 | ('include', 'run:include', 'list'), | |
184 | ('omit', 'run:omit', 'list'), | |
185 | ('parallel', 'run:parallel', 'boolean'), | |
186 | ('source', 'run:source', 'list'), | |
187 | ('timid', 'run:timid', 'boolean'), | |
188 | ||
189 | # [report] | |
190 | ('exclude_list', 'report:exclude_lines', 'linelist'), | |
191 | ('ignore_errors', 'report:ignore_errors', 'boolean'), | |
192 | ('include', 'report:include', 'list'), | |
193 | ('omit', 'report:omit', 'list'), | |
194 | ('partial_list', 'report:partial_branches', 'linelist'), | |
195 | ('partial_always_list', 'report:partial_branches_always', 'linelist'), | |
196 | ('precision', 'report:precision', 'int'), | |
197 | ('show_missing', 'report:show_missing', 'boolean'), | |
198 | ||
199 | # [html] | |
200 | ('html_dir', 'html:directory'), | |
201 | ('extra_css', 'html:extra_css'), | |
202 | ('html_title', 'html:title'), | |
203 | ||
204 | # [xml] | |
205 | ('xml_output', 'xml:output'), | |
206 | ] | |
207 | ||
208 | def set_attr_from_config_option(self, cp, attr, where, type_=''): | |
209 | """Set an attribute on self if it exists in the ConfigParser.""" | |
210 | section, option = where.split(":") | |
211 | if cp.has_option(section, option): | |
212 | method = getattr(cp, 'get'+type_) | |
213 | setattr(self, attr, method(section, option)) | |
3499
f2d4b02c7e88
Modified the Python2 coverage files to include the Python2 eflags line and fixed an issue in both variants.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
3495
diff
changeset
|
214 | |
f2d4b02c7e88
Modified the Python2 coverage files to include the Python2 eflags line and fixed an issue in both variants.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
3495
diff
changeset
|
215 | # |
f2d4b02c7e88
Modified the Python2 coverage files to include the Python2 eflags line and fixed an issue in both variants.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
3495
diff
changeset
|
216 | # eflag: FileType = Python2 |