Skip to content

Commit

Permalink
solved an issue where missing dev dependencies were added to the list…
Browse files Browse the repository at this point in the history
… as None (#99)

* solved an issue where missing dev depenencies were added to the list as None
* Added unit test
  • Loading branch information
Florian Maas authored Sep 13, 2022
1 parent df81701 commit 976e6a3
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
2 changes: 1 addition & 1 deletion codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ ignore:
project:
default:
target: auto
threshold: 0%
threshold: .5%
7 changes: 5 additions & 2 deletions deptry/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ def run(self) -> Dict:
imported_modules = [ModuleBuilder(mod, dependencies, dev_dependencies).build() for mod in imported_modules]
imported_modules = [mod for mod in imported_modules if not mod.standard_library]

issues = self._find_issues(imported_modules, dependencies)
issues = self._find_issues(imported_modules, dependencies, dev_dependencies)
ResultLogger(issues=issues).log_and_exit()

def _find_issues(self, imported_modules: List[Module], dependencies: List[Dependency]):
def _find_issues(
self, imported_modules: List[Module], dependencies: List[Dependency], dev_dependencies: List[Dependency]
):
result = {}
if not self.skip_obsolete:
result["obsolete"] = ObsoleteDependenciesFinder(
Expand All @@ -83,6 +85,7 @@ def _find_issues(self, imported_modules: List[Module], dependencies: List[Depend
result["misplaced_dev"] = MisplacedDevDependenciesFinder(
imported_modules=imported_modules,
dependencies=dependencies,
dev_dependencies=dev_dependencies,
ignore_misplaced_dev=self.ignore_misplaced_dev,
).find()
return result
Expand Down
46 changes: 38 additions & 8 deletions deptry/issue_finders/misplaced_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,58 @@ class MisplacedDevDependenciesFinder:
"""

def __init__(
self, imported_modules: List[Module], dependencies: List[Dependency], ignore_misplaced_dev: List[str] = []
self,
imported_modules: List[Module],
dependencies: List[Dependency],
dev_dependencies: List[Dependency],
ignore_misplaced_dev: List[str] = [],
) -> None:
self.imported_modules = imported_modules
self.dependencies = dependencies
self.dev_dependencies = dev_dependencies
self.ignore_misplaced_dev = ignore_misplaced_dev

def find(self) -> List[str]:
"""
In this function, we use 'corresponding_package_name' instead of module.package, since it can happen that a
development dependency is not installed, but it's still found to be used in the codebase, due to simple name matching.
In that case, it's added under module.dev_top_levels. _get_package_name is added for these edge-cases.
"""
logging.debug("\nScanning for incorrect development dependencies...")
dev_dependencies = []
misplaced_dev_dependencies = []
for module in self.imported_modules:
logging.debug(f"Scanning module {module.name}...")
if self._is_development_dependency(module):
dev_dependencies.append(module.package)
return dev_dependencies
corresponding_package_name = self._get_package_name(module)
if corresponding_package_name:
if self._is_development_dependency(module, corresponding_package_name):
misplaced_dev_dependencies.append(corresponding_package_name)
return misplaced_dev_dependencies

def _is_development_dependency(self, module: Module) -> bool:
def _is_development_dependency(self, module: Module, corresponding_package_name: str) -> bool:
if module.is_dev_dependency:
if module.name in self.ignore_misplaced_dev:
logging.debug(
f"Module '{module.package}' found to be a misplaced development dependency, but ignoring."
f"Module '{corresponding_package_name}' found to be a misplaced development dependency, but ignoring."
)
else:
logging.debug(f"Dependency '{module.package}' marked as a misplaced development dependency.")
logging.debug(
f"Dependency '{corresponding_package_name}' marked as a misplaced development dependency."
)
return True
return False

def _get_package_name(self, module: Module):
if module.package:
return module.package
if module.dev_top_levels:
if len(module.dev_top_levels) > 1:
logging.debug(
f"Module {module.name} is found in the top-level module names of multiple development dependencies. Skipping."
)
elif len(module.dev_top_levels) == 0:
logging.debug(
f"Module {module.name} has no metadata and it is not found in any top-level module names. Skipping."
)
else:
return module.dev_top_levels[0]
return None
12 changes: 12 additions & 0 deletions tests/test_missing_dependencies_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@ def test_simple_with_ignore():
imported_modules=modules, dependencies=dependencies, ignore_missing=["foobar"]
).find()
assert len(deps) == 0


def test_no_error():
"""
This should run without an error, even though `foo` is not installed.
"""

dep = Dependency("foo")
module = ModuleBuilder("foo", [dep]).build()

deps = MissingDependenciesFinder(imported_modules=[module], dependencies=[dep]).find()
assert len(deps) == 0

0 comments on commit 976e6a3

Please sign in to comment.