Skip to content

Commit 1e3f297

Browse files
committed
traverse_project: Better handle overlap between pyenv and code/deps dir
Issue #465 highlights a peculiar case where the top-level project directory is also itself the root of a virtualenv. Our traversal code will skip any (given or detected) Python environment, under the assumption that we never want to analyze code/deps from a package installed within. However, we here have a special case where -- from the traversal code's POV -- we have found a pyenv rooted at a directory that also appears in the given settings.code and/or settings.deps (by default settings.code, settings.deps and settings.pyenvs are all "."). Work around this special case as follows: When a Python environment is found rooted at a path that is _also_ directly given in either settings.code or settings.deps, then we _don't_ want to skip traversal of the entire directory, rather we only skip traversal of the specific subdirectories that form the actual contents of the environment: - Any package dirs found by validate_pyenv_source() (i.e. any "site-packages" dirs). - The "bin/" (or "Scripts\" on Windows) subdir where we expect to find any tools installed into the environment. We could probably extend this handling to _any_ Python environment (including those found after we start the traversal proper), but I'm not 100% sure that this won't trigger false positives where some weird Python environment (e.g. a Conda or poetry2nix environment) happens to contain extra "stuff" missing from the above list that would adversely affect our analysis.
1 parent f9eff65 commit 1e3f297

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

fawltydeps/traverse_project.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Traverse a project to identify appropriate inputs to FawltyDeps."""
22

33
import logging
4+
import sys
45
from collections.abc import Iterator
56
from collections.abc import Set as AbstractSet
67
from pathlib import Path
@@ -131,7 +132,18 @@ def find_sources( # noqa: C901, PLR0912, PLR0915
131132
if package_dirs is not None: # Python environment dir given directly
132133
logger.debug(f"find_sources() Found {package_dirs}")
133134
yield from package_dirs
134-
traversal.skip_dir(path) # disable traversal of path below
135+
if path in (settings.code | settings.deps):
136+
# We are also searching this dir for code/deps, hence we should
137+
# not skip it altogether, but rather only skip the parts of it
138+
# that likely contain installed 3rd-party packages
139+
for pyenv_src in package_dirs:
140+
traversal.skip_dir(pyenv_src.path)
141+
if sys.platform.startswith("win"): # Windows
142+
traversal.skip_dir(path / "Scripts")
143+
else: # Assume POSIX
144+
traversal.skip_dir(path / "bin")
145+
else:
146+
traversal.skip_dir(path) # disable traversal of entire Python env
135147
else: # must traverse directory to find Python environments
136148
traversal.add(path, PyEnvSource)
137149

0 commit comments

Comments
 (0)