109 |
109 |
110 |
110 |
111 class InOrOut(object): |
111 class InOrOut(object): |
112 """Machinery for determining what files to measure.""" |
112 """Machinery for determining what files to measure.""" |
113 |
113 |
114 def __init__(self, warn): |
114 def __init__(self, warn, debug): |
115 self.warn = warn |
115 self.warn = warn |
|
116 self.debug = debug |
116 |
117 |
117 # The matchers for should_trace. |
118 # The matchers for should_trace. |
118 self.source_match = None |
119 self.source_match = None |
119 self.source_pkgs_match = None |
120 self.source_pkgs_match = None |
120 self.pylib_paths = self.cover_paths = None |
121 self.pylib_paths = self.cover_paths = None |
129 self.source_pkgs_unmatched = [] |
130 self.source_pkgs_unmatched = [] |
130 self.omit = self.include = None |
131 self.omit = self.include = None |
131 |
132 |
132 def configure(self, config): |
133 def configure(self, config): |
133 """Apply the configuration to get ready for decision-time.""" |
134 """Apply the configuration to get ready for decision-time.""" |
|
135 self.source_pkgs.extend(config.source_pkgs) |
134 for src in config.source or []: |
136 for src in config.source or []: |
135 if os.path.isdir(src): |
137 if os.path.isdir(src): |
136 self.source.append(canonical_filename(src)) |
138 self.source.append(canonical_filename(src)) |
137 else: |
139 else: |
138 self.source_pkgs.append(src) |
140 self.source_pkgs.append(src) |
175 import contracts |
177 import contracts |
176 import six |
178 import six |
177 for mod in [contracts, six]: |
179 for mod in [contracts, six]: |
178 self.cover_paths.append(canonical_path(mod)) |
180 self.cover_paths.append(canonical_path(mod)) |
179 |
181 |
|
182 def debug(msg): |
|
183 if self.debug: |
|
184 self.debug.write(msg) |
|
185 |
180 # Create the matchers we need for should_trace |
186 # Create the matchers we need for should_trace |
181 if self.source or self.source_pkgs: |
187 if self.source or self.source_pkgs: |
182 self.source_match = TreeMatcher(self.source) |
188 against = [] |
183 self.source_pkgs_match = ModuleMatcher(self.source_pkgs) |
189 if self.source: |
|
190 self.source_match = TreeMatcher(self.source) |
|
191 against.append("trees {!r}".format(self.source_match)) |
|
192 if self.source_pkgs: |
|
193 self.source_pkgs_match = ModuleMatcher(self.source_pkgs) |
|
194 against.append("modules {!r}".format(self.source_pkgs_match)) |
|
195 debug("Source matching against " + " and ".join(against)) |
184 else: |
196 else: |
185 if self.cover_paths: |
197 if self.cover_paths: |
186 self.cover_match = TreeMatcher(self.cover_paths) |
198 self.cover_match = TreeMatcher(self.cover_paths) |
|
199 debug("Coverage code matching: {!r}".format(self.cover_match)) |
187 if self.pylib_paths: |
200 if self.pylib_paths: |
188 self.pylib_match = TreeMatcher(self.pylib_paths) |
201 self.pylib_match = TreeMatcher(self.pylib_paths) |
|
202 debug("Python stdlib matching: {!r}".format(self.pylib_match)) |
189 if self.include: |
203 if self.include: |
190 self.include_match = FnmatchMatcher(self.include) |
204 self.include_match = FnmatchMatcher(self.include) |
|
205 debug("Include matching: {!r}".format(self.include_match)) |
191 if self.omit: |
206 if self.omit: |
192 self.omit_match = FnmatchMatcher(self.omit) |
207 self.omit_match = FnmatchMatcher(self.omit) |
|
208 debug("Omit matching: {!r}".format(self.omit_match)) |
193 |
209 |
194 def should_trace(self, filename, frame=None): |
210 def should_trace(self, filename, frame=None): |
195 """Decide whether to trace execution in `filename`, with a reason. |
211 """Decide whether to trace execution in `filename`, with a reason. |
196 |
212 |
197 This function is called from the trace function. As each new file name |
213 This function is called from the trace function. As each new file name |
307 |
323 |
308 # If the user specified source or include, then that's authoritative |
324 # If the user specified source or include, then that's authoritative |
309 # about the outer bound of what to measure and we don't have to apply |
325 # about the outer bound of what to measure and we don't have to apply |
310 # any canned exclusions. If they didn't, then we have to exclude the |
326 # any canned exclusions. If they didn't, then we have to exclude the |
311 # stdlib and coverage.py directories. |
327 # stdlib and coverage.py directories. |
312 if self.source_match: |
328 if self.source_match or self.source_pkgs_match: |
313 if self.source_pkgs_match.match(modulename): |
329 extra = "" |
314 if modulename in self.source_pkgs_unmatched: |
330 ok = False |
315 self.source_pkgs_unmatched.remove(modulename) |
331 if self.source_pkgs_match: |
316 elif not self.source_match.match(filename): |
332 if self.source_pkgs_match.match(modulename): |
317 return "falls outside the --source trees" |
333 ok = True |
|
334 if modulename in self.source_pkgs_unmatched: |
|
335 self.source_pkgs_unmatched.remove(modulename) |
|
336 else: |
|
337 extra = "module {!r} ".format(modulename) |
|
338 if not ok and self.source_match: |
|
339 if self.source_match.match(filename): |
|
340 ok = True |
|
341 if not ok: |
|
342 return extra + "falls outside the --source spec" |
318 elif self.include_match: |
343 elif self.include_match: |
319 if not self.include_match.match(filename): |
344 if not self.include_match.match(filename): |
320 return "falls outside the --include trees" |
345 return "falls outside the --include trees" |
321 else: |
346 else: |
322 # If we aren't supposed to trace installed code, then check if this |
347 # If we aren't supposed to trace installed code, then check if this |