|
24 | 24 |
|
25 | 25 | from coverage import env
|
26 | 26 | from coverage.disposition import FileDisposition, disposition_init
|
27 |
| -from coverage.exceptions import CoverageException, PluginError |
| 27 | +from coverage.exceptions import ConfigError, CoverageException, PluginError |
28 | 28 | from coverage.files import TreeMatcher, GlobMatcher, ModuleMatcher
|
29 | 29 | from coverage.files import prep_patterns, find_python_files, canonical_filename
|
30 | 30 | from coverage.misc import isolate_module, sys_modules_saved
|
@@ -183,14 +183,25 @@ def __init__(
|
183 | 183 | self.debug = debug
|
184 | 184 | self.include_namespace_packages = include_namespace_packages
|
185 | 185 |
|
186 |
| - self.source: list[str] = [] |
187 | 186 | self.source_pkgs: list[str] = []
|
188 | 187 | self.source_pkgs.extend(config.source_pkgs)
|
| 188 | + self.source_dirs: list[str] = [] |
| 189 | + self.source_dirs.extend(config.source_dirs) |
189 | 190 | for src in config.source or []:
|
190 | 191 | if os.path.isdir(src):
|
191 |
| - self.source.append(canonical_filename(src)) |
| 192 | + self.source_dirs.append(src) |
192 | 193 | else:
|
193 | 194 | self.source_pkgs.append(src)
|
| 195 | + |
| 196 | + # Canonicalize everything in `source_dirs`. |
| 197 | + # Also confirm that they actually are directories. |
| 198 | + for i, src in enumerate(self.source_dirs): |
| 199 | + self.source_dirs[i] = canonical_filename(src) |
| 200 | + |
| 201 | + if not os.path.isdir(src): |
| 202 | + raise ConfigError(f"Source dir doesn't exist, or is not a directory: {src}") |
| 203 | + |
| 204 | + |
194 | 205 | self.source_pkgs_unmatched = self.source_pkgs[:]
|
195 | 206 |
|
196 | 207 | self.include = prep_patterns(config.run_include)
|
@@ -225,10 +236,10 @@ def _debug(msg: str) -> None:
|
225 | 236 | self.pylib_match = None
|
226 | 237 | self.include_match = self.omit_match = None
|
227 | 238 |
|
228 |
| - if self.source or self.source_pkgs: |
| 239 | + if self.source_dirs or self.source_pkgs: |
229 | 240 | against = []
|
230 |
| - if self.source: |
231 |
| - self.source_match = TreeMatcher(self.source, "source") |
| 241 | + if self.source_dirs: |
| 242 | + self.source_match = TreeMatcher(self.source_dirs, "source") |
232 | 243 | against.append(f"trees {self.source_match!r}")
|
233 | 244 | if self.source_pkgs:
|
234 | 245 | self.source_pkgs_match = ModuleMatcher(self.source_pkgs, "source_pkgs")
|
@@ -277,7 +288,7 @@ def _debug(msg: str) -> None:
|
277 | 288 | )
|
278 | 289 | self.source_in_third_paths.add(pathdir)
|
279 | 290 |
|
280 |
| - for src in self.source: |
| 291 | + for src in self.source_dirs: |
281 | 292 | if self.third_match.match(src):
|
282 | 293 | _debug(f"Source in third-party: source directory {src!r}")
|
283 | 294 | self.source_in_third_paths.add(src)
|
@@ -449,12 +460,12 @@ def check_include_omit_etc(self, filename: str, frame: FrameType | None) -> str
|
449 | 460 | def warn_conflicting_settings(self) -> None:
|
450 | 461 | """Warn if there are settings that conflict."""
|
451 | 462 | if self.include:
|
452 |
| - if self.source or self.source_pkgs: |
| 463 | + if self.source_dirs or self.source_pkgs: |
453 | 464 | self.warn("--include is ignored because --source is set", slug="include-ignored")
|
454 | 465 |
|
455 | 466 | def warn_already_imported_files(self) -> None:
|
456 | 467 | """Warn if files have already been imported that we will be measuring."""
|
457 |
| - if self.include or self.source or self.source_pkgs: |
| 468 | + if self.include or self.source_dirs or self.source_pkgs: |
458 | 469 | warned = set()
|
459 | 470 | for mod in list(sys.modules.values()):
|
460 | 471 | filename = getattr(mod, "__file__", None)
|
@@ -527,7 +538,7 @@ def find_possibly_unexecuted_files(self) -> Iterable[tuple[str, str | None]]:
|
527 | 538 | pkg_file = source_for_file(cast(str, sys.modules[pkg].__file__))
|
528 | 539 | yield from self._find_executable_files(canonical_path(pkg_file))
|
529 | 540 |
|
530 |
| - for src in self.source: |
| 541 | + for src in self.source_dirs: |
531 | 542 | yield from self._find_executable_files(src)
|
532 | 543 |
|
533 | 544 | def _find_plugin_files(self, src_dir: str) -> Iterable[tuple[str, str]]:
|
|
0 commit comments