From afef9dde29e63ae7aafea200b5fdf116e6142aa4 Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 12 Jul 2024 19:21:18 +0200 Subject: [PATCH 01/12] Initial implementation --- python/deptry/core.py | 11 +++-- python/deptry/violations/__init__.py | 4 ++ python/deptry/violations/base.py | 18 ++++---- .../violations/dep001_missing/finder.py | 5 ++- .../deptry/violations/dep002_unused/finder.py | 2 - .../violations/dep003_transitive/finder.py | 5 ++- .../violations/dep004_misplaced_dev/finder.py | 5 ++- .../dep005_standard_library/__init__.py | 0 .../dep005_standard_library/finder.py | 43 +++++++++++++++++++ .../dep005_standard_library/violation.py | 19 ++++++++ python/deptry/violations/finder.py | 20 +++++++-- tests/data/pep_621_project/pyproject.toml | 1 + tests/data/pep_621_project/src/main.py | 1 + 13 files changed, 108 insertions(+), 26 deletions(-) create mode 100644 python/deptry/violations/dep005_standard_library/__init__.py create mode 100644 python/deptry/violations/dep005_standard_library/finder.py create mode 100644 python/deptry/violations/dep005_standard_library/violation.py diff --git a/python/deptry/core.py b/python/deptry/core.py index d6cf64e3..3d3d6f8f 100644 --- a/python/deptry/core.py +++ b/python/deptry/core.py @@ -74,14 +74,13 @@ def run(self) -> None: ) for module, locations in get_imported_modules_from_list_of_files(python_files).items() ] - imported_modules_with_locations = [ - module_with_locations - for module_with_locations in imported_modules_with_locations - if not module_with_locations.module.standard_library - ] violations = find_violations( - imported_modules_with_locations, dependencies_extract.dependencies, self.ignore, self.per_rule_ignores + imported_modules_with_locations, + dependencies_extract.dependencies, + self.ignore, + self.per_rule_ignores, + stdlib_modules, ) TextReporter(violations, use_ansi=not self.no_ansi).report() diff --git a/python/deptry/violations/__init__.py b/python/deptry/violations/__init__.py index 4caf02f7..a9b328c1 100644 --- a/python/deptry/violations/__init__.py +++ b/python/deptry/violations/__init__.py @@ -9,16 +9,20 @@ from deptry.violations.dep003_transitive.violation import DEP003TransitiveDependencyViolation from deptry.violations.dep004_misplaced_dev.finder import DEP004MisplacedDevDependenciesFinder from deptry.violations.dep004_misplaced_dev.violation import DEP004MisplacedDevDependencyViolation +from deptry.violations.dep005_standard_library.finder import DEP005StandardLibraryDependencyFinder +from deptry.violations.dep005_standard_library.violation import DEP005StandardLibraryDependencyViolation __all__ = ( "DEP001MissingDependencyViolation", "DEP002UnusedDependencyViolation", "DEP003TransitiveDependencyViolation", "DEP004MisplacedDevDependencyViolation", + "DEP005StandardLibraryDependencyViolation", "DEP001MissingDependenciesFinder", "DEP002UnusedDependenciesFinder", "DEP003TransitiveDependenciesFinder", "DEP004MisplacedDevDependenciesFinder", + "DEP005StandardLibraryDependencyFinder", "Violation", "ViolationsFinder", ) diff --git a/python/deptry/violations/base.py b/python/deptry/violations/base.py index f513e9a5..99be2be6 100644 --- a/python/deptry/violations/base.py +++ b/python/deptry/violations/base.py @@ -10,7 +10,6 @@ from deptry.module import Module, ModuleLocations -@dataclass class ViolationsFinder(ABC): """Base class for all issues finders. @@ -23,18 +22,19 @@ class ViolationsFinder(ABC): dependencies: A list of Dependency objects representing the project's dependencies. ignored_modules: A tuple of module names to ignore when scanning for issues. Defaults to an empty tuple. - """ violation: ClassVar[type[Violation]] - imported_modules_with_locations: list[ModuleLocations] - dependencies: list[Dependency] - ignored_modules: tuple[str, ...] = () - @abstractmethod - def find(self) -> list[Violation]: - """Find issues about dependencies.""" - raise NotImplementedError() + def __init__( + self, + imported_modules_with_locations: list[ModuleLocations], + dependencies: list[Dependency], + ignored_modules: tuple[str, ...] = (), + ): + self.imported_modules_with_locations = imported_modules_with_locations + self.dependencies = dependencies + self.ignored_modules = ignored_modules @dataclass diff --git a/python/deptry/violations/dep001_missing/finder.py b/python/deptry/violations/dep001_missing/finder.py index 45f18547..39db704d 100644 --- a/python/deptry/violations/dep001_missing/finder.py +++ b/python/deptry/violations/dep001_missing/finder.py @@ -1,7 +1,6 @@ from __future__ import annotations import logging -from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.violations.base import ViolationsFinder @@ -12,7 +11,6 @@ from deptry.violations.base import Violation -@dataclass class DEP001MissingDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which ones are missing. @@ -27,6 +25,9 @@ def find(self) -> list[Violation]: for module_with_locations in self.imported_modules_with_locations: module = module_with_locations.module + if module.standard_library: + continue + logging.debug("Scanning module %s...", module.name) if self._is_missing(module): diff --git a/python/deptry/violations/dep002_unused/finder.py b/python/deptry/violations/dep002_unused/finder.py index f364e39a..62340d53 100644 --- a/python/deptry/violations/dep002_unused/finder.py +++ b/python/deptry/violations/dep002_unused/finder.py @@ -1,7 +1,6 @@ from __future__ import annotations import logging -from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.imports.location import Location @@ -13,7 +12,6 @@ from deptry.violations import Violation -@dataclass class DEP002UnusedDependenciesFinder(ViolationsFinder): """ Finds unused dependencies by comparing a list of imported modules to a list of project dependencies. diff --git a/python/deptry/violations/dep003_transitive/finder.py b/python/deptry/violations/dep003_transitive/finder.py index dcca3a4c..8102d8b7 100644 --- a/python/deptry/violations/dep003_transitive/finder.py +++ b/python/deptry/violations/dep003_transitive/finder.py @@ -1,7 +1,6 @@ from __future__ import annotations import logging -from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.violations.base import ViolationsFinder @@ -12,7 +11,6 @@ from deptry.violations import Violation -@dataclass class DEP003TransitiveDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which ones are transitive. @@ -34,6 +32,9 @@ def find(self) -> list[Violation]: for module_with_locations in self.imported_modules_with_locations: module = module_with_locations.module + if module.standard_library: + continue + logging.debug("Scanning module %s...", module.name) if self._is_transitive(module): diff --git a/python/deptry/violations/dep004_misplaced_dev/finder.py b/python/deptry/violations/dep004_misplaced_dev/finder.py index 6fe506ad..bb0e8350 100644 --- a/python/deptry/violations/dep004_misplaced_dev/finder.py +++ b/python/deptry/violations/dep004_misplaced_dev/finder.py @@ -1,7 +1,6 @@ from __future__ import annotations import logging -from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.violations.base import ViolationsFinder @@ -12,7 +11,6 @@ from deptry.violations import Violation -@dataclass class DEP004MisplacedDevDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which development dependencies @@ -35,6 +33,9 @@ def find(self) -> list[Violation]: for module_with_locations in self.imported_modules_with_locations: module = module_with_locations.module + if module.standard_library: + continue + logging.debug("Scanning module %s...", module.name) corresponding_package_name = self._get_package_name(module) diff --git a/python/deptry/violations/dep005_standard_library/__init__.py b/python/deptry/violations/dep005_standard_library/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py new file mode 100644 index 00000000..be434ee8 --- /dev/null +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING + +from deptry.imports.location import Location +from deptry.violations.base import ViolationsFinder +from deptry.violations.dep005_standard_library.violation import DEP005StandardLibraryDependencyViolation + +if TYPE_CHECKING: + from deptry.dependency import Dependency + from deptry.module import ModuleLocations + from deptry.violations import Violation + + +class DEP005StandardLibraryDependencyFinder(ViolationsFinder): + """ + Finds dependencies that are part of the standard library but are defined as dependencies. + """ + + violation = DEP005StandardLibraryDependencyViolation + + def __init__( + self, + imported_modules_with_locations: list[ModuleLocations], + dependencies: list[Dependency], + stdlib_modules: set[str], + ignored_modules: tuple[str, ...] = (), + ): + super().__init__(imported_modules_with_locations, dependencies, ignored_modules) + self.stdlib_modules = stdlib_modules + + def find(self) -> list[Violation]: + logging.debug("\nScanning for dependencies that are part of the standard library...") + stdlib_violations: list[Violation] = [] + + for dependency in self.dependencies: + logging.debug("Scanning module %s...", dependency.name) + + if dependency.name in self.stdlib_modules: + stdlib_violations.append(self.violation(dependency, Location(dependency.definition_file))) + + return stdlib_violations diff --git a/python/deptry/violations/dep005_standard_library/violation.py b/python/deptry/violations/dep005_standard_library/violation.py new file mode 100644 index 00000000..384f2d24 --- /dev/null +++ b/python/deptry/violations/dep005_standard_library/violation.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING, ClassVar + +from deptry.violations.base import Violation + +if TYPE_CHECKING: + from deptry.module import Module + + +@dataclass +class DEP005StandardLibraryDependencyViolation(Violation): + error_code: ClassVar[str] = "DEP005" + error_template: ClassVar[str] = "'{name}' defined as a dependency but it's part of the standard library" + issue: Module + + def get_error_message(self) -> str: + return self.error_template.format(name=self.issue.name) diff --git a/python/deptry/violations/finder.py b/python/deptry/violations/finder.py index b51a1da9..cf26fc64 100644 --- a/python/deptry/violations/finder.py +++ b/python/deptry/violations/finder.py @@ -8,6 +8,7 @@ DEP002UnusedDependenciesFinder, DEP003TransitiveDependenciesFinder, DEP004MisplacedDevDependenciesFinder, + DEP005StandardLibraryDependencyFinder, ) if TYPE_CHECKING: @@ -31,6 +32,7 @@ def find_violations( dependencies: list[Dependency], ignore: tuple[str, ...], per_rule_ignores: Mapping[str, tuple[str, ...]], + stdlib_modules: set[str], ) -> list[Violation]: violations = [] @@ -38,12 +40,24 @@ def find_violations( if violation_finder.violation.error_code not in ignore: violations.extend( violation_finder( - imported_modules_with_locations, - dependencies, - per_rule_ignores.get(violation_finder.violation.error_code, ()), + imported_modules_with_locations=imported_modules_with_locations, + dependencies=dependencies, + ignored_modules=per_rule_ignores.get(violation_finder.violation.error_code, ()), ).find() ) + # Since DEP005StandardLibraryDependencyFinder has a different constructor than the other 4 classes, + # we handle it separately. + if DEP005StandardLibraryDependencyFinder.violation.error_code not in ignore: + violations.extend( + DEP005StandardLibraryDependencyFinder( + imported_modules_with_locations=imported_modules_with_locations, + dependencies=dependencies, + ignored_modules=per_rule_ignores.get(violation_finder.violation.error_code, ()), + stdlib_modules=stdlib_modules, + ).find() + ) + return _get_sorted_violations(violations) diff --git a/tests/data/pep_621_project/pyproject.toml b/tests/data/pep_621_project/pyproject.toml index d845bb95..ad9e1115 100644 --- a/tests/data/pep_621_project/pyproject.toml +++ b/tests/data/pep_621_project/pyproject.toml @@ -11,6 +11,7 @@ dependencies = [ "click>=8.1.3", "requests>=2.28.1", "pkginfo>=1.8.3", + "asyncio", ] [project.optional-dependencies] diff --git a/tests/data/pep_621_project/src/main.py b/tests/data/pep_621_project/src/main.py index 2ee666ac..e38176f5 100644 --- a/tests/data/pep_621_project/src/main.py +++ b/tests/data/pep_621_project/src/main.py @@ -5,3 +5,4 @@ import click import white as w from urllib3 import contrib +import asyncio From c82c1e32cac68180a4e8878c6ccb715ff97a5d34 Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 12 Jul 2024 20:40:39 +0200 Subject: [PATCH 02/12] add tests and docs --- docs/rules-violations.md | 34 +++++++++++++++ .../dep005_standard_library/finder.py | 10 +++++ tests/functional/cli/test_cli_pep_621.py | 8 ++++ .../dep005_standard_library/__init__.py | 0 .../dep005_standard_library/test_finder.py | 42 +++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 tests/unit/violations/dep005_standard_library/__init__.py create mode 100644 tests/unit/violations/dep005_standard_library/test_finder.py diff --git a/docs/rules-violations.md b/docs/rules-violations.md index caf8166a..5aa49bbe 100644 --- a/docs/rules-violations.md +++ b/docs/rules-violations.md @@ -8,6 +8,7 @@ _deptry_ checks your project against the following rules related to dependencies | DEP002 | Project should not contain unused dependencies | [link](#unused-dependencies-dep002) | | DEP003 | Project should not use transitive dependencies | [link](#transitive-dependencies-dep003) | | DEP004 | Project should not use development dependencies in non-development code | [link](#misplaced-development-dependencies-dep004) | +| DEP005 | Project should not contain dependencies that are in the standard library | [link](#standard-library-dependencies-dep005) | Any of the checks can be disabled with the [`ignore`](usage.md#ignore) flag. Specific dependencies or modules can be ignored with the [`per-rule-ignores`](usage.md#per-rule-ignores) flag. @@ -170,3 +171,36 @@ dependencies = [ [tool.pdm.dev-dependencies] test = ["pytest==7.2.0"] ``` + +## Standard library dependencies (DEP005) + +Dependencies that are part of the Python standard library should not be defined as dependencies in your project. + +### Example + +On a project with the following dependencies: + +```toml +[project] +dependencies = [ + "asyncio", +] +``` + +and the following `main.py` that is the only Python file in the project: + +```python +import asyncio + +def async_example(): + return asyncio.run(some_coroutine()) +``` + +_deptry_ will report `asyncio` as a standard library dependency because it is part of the standard library, yet it is defined as a dependency in the project. + +To fix the issue, `asyncio` should be removed from `[project.dependencies]`: + +```toml +[project] +dependencies = [] +``` diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py index be434ee8..9f6057de 100644 --- a/python/deptry/violations/dep005_standard_library/finder.py +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -38,6 +38,16 @@ def find(self) -> list[Violation]: logging.debug("Scanning module %s...", dependency.name) if dependency.name in self.stdlib_modules: + if dependency.name in self.ignored_modules: + logging.debug( + "Dependency '%s' found to be a dependency that is part of the standard library, but ignoring.", + dependency.name, + ) + continue + + logging.debug( + "Dependency '%s' marked as a dependency that is part of the standard library.", dependency.name + ) stdlib_violations.append(self.violation(dependency, Location(dependency.definition_file))) return stdlib_violations diff --git a/tests/functional/cli/test_cli_pep_621.py b/tests/functional/cli/test_cli_pep_621.py index 3939d1f6..0d1837b6 100644 --- a/tests/functional/cli/test_cli_pep_621.py +++ b/tests/functional/cli/test_cli_pep_621.py @@ -47,6 +47,14 @@ def test_cli_with_pep_621(pip_venv_factory: PipVenvFactory) -> None: "module": "matplotlib", "location": {"file": str(Path("pyproject.toml")), "line": None, "column": None}, }, + { + "error": { + "code": "DEP005", + "message": "'asyncio' defined as a dependency but it's part of the standard library", + }, + "module": "asyncio", + "location": {"file": "pyproject.toml", "line": None, "column": None}, + }, { "error": {"code": "DEP004", "message": "'black' imported but declared as a dev dependency"}, "module": "black", diff --git a/tests/unit/violations/dep005_standard_library/__init__.py b/tests/unit/violations/dep005_standard_library/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/violations/dep005_standard_library/test_finder.py b/tests/unit/violations/dep005_standard_library/test_finder.py new file mode 100644 index 00000000..62a1ea77 --- /dev/null +++ b/tests/unit/violations/dep005_standard_library/test_finder.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from pathlib import Path + +from deptry.dependency import Dependency +from deptry.imports.location import Location +from deptry.module import ModuleBuilder, ModuleLocations +from deptry.violations import DEP005StandardLibraryDependencyFinder, DEP005StandardLibraryDependencyViolation + + +def test_simple() -> None: + dependency_asyncio = Dependency("asyncio", Path("pyproject.toml")) + dependencies = [dependency_asyncio] + modules_locations = [ + ModuleLocations( + ModuleBuilder("asyncio", {"foo"}, frozenset(), dependencies).build(), [Location(Path("foo.py"), 1, 2)] + ) + ] + + assert DEP005StandardLibraryDependencyFinder( + imported_modules_with_locations=modules_locations, dependencies=dependencies, stdlib_modules={"asyncio"} + ).find() == [DEP005StandardLibraryDependencyViolation(dependency_asyncio, Location(Path("pyproject.toml")))] + + +def test_simple_with_ignore() -> None: + dependency_asyncio = Dependency("asyncio", Path("pyproject.toml")) + dependencies = [dependency_asyncio] + modules_locations = [ + ModuleLocations( + ModuleBuilder("asyncio", {"foo"}, frozenset(), dependencies).build(), [Location(Path("foo.py"), 1, 2)] + ) + ] + + assert ( + DEP005StandardLibraryDependencyFinder( + imported_modules_with_locations=modules_locations, + dependencies=dependencies, + stdlib_modules={"asyncio"}, + ignored_modules=("asyncio",), + ).find() + == [] + ) From 695e35def0399cebf1af689efdee43f79da01c9e Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 12 Jul 2024 21:11:26 +0200 Subject: [PATCH 03/12] fix mypy --- python/deptry/violations/base.py | 5 +++++ python/deptry/violations/dep005_standard_library/finder.py | 2 +- .../deptry/violations/dep005_standard_library/violation.py | 4 ++-- python/deptry/violations/finder.py | 2 +- .../unit/violations/dep005_standard_library/test_finder.py | 6 ++++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/python/deptry/violations/base.py b/python/deptry/violations/base.py index 99be2be6..3b1afae4 100644 --- a/python/deptry/violations/base.py +++ b/python/deptry/violations/base.py @@ -36,6 +36,11 @@ def __init__( self.dependencies = dependencies self.ignored_modules = ignored_modules + @abstractmethod + def find(self) -> list[Violation]: + """Find issues about dependencies.""" + raise NotImplementedError() + @dataclass class Violation(ABC): diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py index 9f6057de..acf7ae5e 100644 --- a/python/deptry/violations/dep005_standard_library/finder.py +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -24,7 +24,7 @@ def __init__( self, imported_modules_with_locations: list[ModuleLocations], dependencies: list[Dependency], - stdlib_modules: set[str], + stdlib_modules: frozenset[str], ignored_modules: tuple[str, ...] = (), ): super().__init__(imported_modules_with_locations, dependencies, ignored_modules) diff --git a/python/deptry/violations/dep005_standard_library/violation.py b/python/deptry/violations/dep005_standard_library/violation.py index 384f2d24..c08d82b9 100644 --- a/python/deptry/violations/dep005_standard_library/violation.py +++ b/python/deptry/violations/dep005_standard_library/violation.py @@ -6,14 +6,14 @@ from deptry.violations.base import Violation if TYPE_CHECKING: - from deptry.module import Module + from deptry.dependency import Dependency @dataclass class DEP005StandardLibraryDependencyViolation(Violation): error_code: ClassVar[str] = "DEP005" error_template: ClassVar[str] = "'{name}' defined as a dependency but it's part of the standard library" - issue: Module + issue: Dependency def get_error_message(self) -> str: return self.error_template.format(name=self.issue.name) diff --git a/python/deptry/violations/finder.py b/python/deptry/violations/finder.py index cf26fc64..ca33c4fa 100644 --- a/python/deptry/violations/finder.py +++ b/python/deptry/violations/finder.py @@ -32,7 +32,7 @@ def find_violations( dependencies: list[Dependency], ignore: tuple[str, ...], per_rule_ignores: Mapping[str, tuple[str, ...]], - stdlib_modules: set[str], + stdlib_modules: frozenset[str], ) -> list[Violation]: violations = [] diff --git a/tests/unit/violations/dep005_standard_library/test_finder.py b/tests/unit/violations/dep005_standard_library/test_finder.py index 62a1ea77..ef39a5be 100644 --- a/tests/unit/violations/dep005_standard_library/test_finder.py +++ b/tests/unit/violations/dep005_standard_library/test_finder.py @@ -18,7 +18,9 @@ def test_simple() -> None: ] assert DEP005StandardLibraryDependencyFinder( - imported_modules_with_locations=modules_locations, dependencies=dependencies, stdlib_modules={"asyncio"} + imported_modules_with_locations=modules_locations, + dependencies=dependencies, + stdlib_modules=frozenset(["asyncio"]), ).find() == [DEP005StandardLibraryDependencyViolation(dependency_asyncio, Location(Path("pyproject.toml")))] @@ -35,7 +37,7 @@ def test_simple_with_ignore() -> None: DEP005StandardLibraryDependencyFinder( imported_modules_with_locations=modules_locations, dependencies=dependencies, - stdlib_modules={"asyncio"}, + stdlib_modules=frozenset(["asyncio"]), ignored_modules=("asyncio",), ).find() == [] From 3ec96341303ff67e87a645120ab7ec4d641dcdca Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 12 Jul 2024 21:25:54 +0200 Subject: [PATCH 04/12] docs fix --- docs/rules-violations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules-violations.md b/docs/rules-violations.md index 5aa49bbe..58cd296e 100644 --- a/docs/rules-violations.md +++ b/docs/rules-violations.md @@ -187,7 +187,7 @@ dependencies = [ ] ``` -and the following `main.py` that is the only Python file in the project: +and the following `main.py` in the project: ```python import asyncio From 9aff3163ce32b89eb675d9dcb67aaac49bc8fcae Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 12 Jul 2024 21:43:00 +0200 Subject: [PATCH 05/12] rename stdlib_modules to avoid acronyms --- python/deptry/core.py | 8 ++++---- python/deptry/module.py | 8 ++++---- .../violations/dep005_standard_library/finder.py | 6 +++--- python/deptry/violations/finder.py | 4 ++-- scripts/generate_stdlibs.py | 12 ++++++------ tests/unit/test_core.py | 8 ++++---- .../dep005_standard_library/test_finder.py | 4 ++-- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/python/deptry/core.py b/python/deptry/core.py index 3d3d6f8f..74080e0a 100644 --- a/python/deptry/core.py +++ b/python/deptry/core.py @@ -59,14 +59,14 @@ def run(self) -> None: python_files = self._find_python_files() local_modules = self._get_local_modules() - stdlib_modules = self._get_stdlib_modules() + standard_library_modules = self._get_standard_library_modules() imported_modules_with_locations = [ ModuleLocations( ModuleBuilder( module, local_modules, - stdlib_modules, + standard_library_modules, dependencies_extract.dependencies, dependencies_extract.dev_dependencies, ).build(), @@ -80,7 +80,7 @@ def run(self) -> None: dependencies_extract.dependencies, self.ignore, self.per_rule_ignores, - stdlib_modules, + standard_library_modules, ) TextReporter(violations, use_ansi=not self.no_ansi).report() @@ -125,7 +125,7 @@ def _is_local_module(path: Path) -> bool: ) @staticmethod - def _get_stdlib_modules() -> frozenset[str]: + def _get_standard_library_modules() -> frozenset[str]: if sys.version_info[:2] >= (3, 10): return sys.stdlib_module_names diff --git a/python/deptry/module.py b/python/deptry/module.py index 0e36c5c0..c6b4c7aa 100644 --- a/python/deptry/module.py +++ b/python/deptry/module.py @@ -64,7 +64,7 @@ def __init__( self, name: str, local_modules: set[str], - stdlib_modules: frozenset[str], + standard_library_modules: frozenset[str], dependencies: list[Dependency] | None = None, dev_dependencies: list[Dependency] | None = None, ) -> None: @@ -74,13 +74,13 @@ def __init__( Args: name: The name of the imported module local_modules: The list of local modules - stdlib_modules: The list of Python stdlib modules + standard_library_modules: The list of Python stdlib modules dependencies: A list of the project's dependencies dev_dependencies: A list of the project's development dependencies """ self.name = name self.local_modules = local_modules - self.stdlib_modules = stdlib_modules + self.standard_library_modules = standard_library_modules self.dependencies = dependencies or [] self.dev_dependencies = dev_dependencies or [] @@ -137,7 +137,7 @@ def _get_corresponding_top_levels_from(self, dependencies: list[Dependency]) -> ] def _in_standard_library(self) -> bool: - return self.name in self.stdlib_modules + return self.name in self.standard_library_modules def _is_local_module(self) -> bool: """ diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py index acf7ae5e..dde56d50 100644 --- a/python/deptry/violations/dep005_standard_library/finder.py +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -24,11 +24,11 @@ def __init__( self, imported_modules_with_locations: list[ModuleLocations], dependencies: list[Dependency], - stdlib_modules: frozenset[str], + standard_library_modules: frozenset[str], ignored_modules: tuple[str, ...] = (), ): super().__init__(imported_modules_with_locations, dependencies, ignored_modules) - self.stdlib_modules = stdlib_modules + self.standard_library_modules = standard_library_modules def find(self) -> list[Violation]: logging.debug("\nScanning for dependencies that are part of the standard library...") @@ -37,7 +37,7 @@ def find(self) -> list[Violation]: for dependency in self.dependencies: logging.debug("Scanning module %s...", dependency.name) - if dependency.name in self.stdlib_modules: + if dependency.name in self.standard_library_modules: if dependency.name in self.ignored_modules: logging.debug( "Dependency '%s' found to be a dependency that is part of the standard library, but ignoring.", diff --git a/python/deptry/violations/finder.py b/python/deptry/violations/finder.py index ca33c4fa..663c3f7e 100644 --- a/python/deptry/violations/finder.py +++ b/python/deptry/violations/finder.py @@ -32,7 +32,7 @@ def find_violations( dependencies: list[Dependency], ignore: tuple[str, ...], per_rule_ignores: Mapping[str, tuple[str, ...]], - stdlib_modules: frozenset[str], + standard_library_modules: frozenset[str], ) -> list[Violation]: violations = [] @@ -54,7 +54,7 @@ def find_violations( imported_modules_with_locations=imported_modules_with_locations, dependencies=dependencies, ignored_modules=per_rule_ignores.get(violation_finder.violation.error_code, ()), - stdlib_modules=stdlib_modules, + standard_library_modules=standard_library_modules, ).find() ) diff --git a/scripts/generate_stdlibs.py b/scripts/generate_stdlibs.py index 23b8f706..8e4de10c 100755 --- a/scripts/generate_stdlibs.py +++ b/scripts/generate_stdlibs.py @@ -45,7 +45,7 @@ def handle_data(self, data: str) -> None: self.modules.append(data) -def get_stdlib_modules_for_python_version(python_version: tuple[int, int]) -> list[str]: +def get_standard_library_modules_for_python_version(python_version: tuple[int, int]) -> list[str]: with urllib.request.urlopen( # noqa: S310 STDLIB_MODULES_URL.format(python_version[0], python_version[1]) ) as response: @@ -60,9 +60,9 @@ def get_stdlib_modules_for_python_version(python_version: tuple[int, int]) -> li return sorted(modules) -def get_stdlib_modules() -> dict[str, list[str]]: +def get_standard_library_modules() -> dict[str, list[str]]: return { - f"{python_version[0]}{python_version[1]}": get_stdlib_modules_for_python_version(python_version) + f"{python_version[0]}{python_version[1]}": get_standard_library_modules_for_python_version(python_version) for python_version in PYTHON_VERSIONS } @@ -78,10 +78,10 @@ def write_stdlibs_file(stdlib_python: dict[str, list[str]]) -> None: values=[ ast.Call( func=ast.Name(id="frozenset"), - args=[ast.Set(elts=[ast.Constant(module) for module in python_stdlib_modules])], + args=[ast.Set(elts=[ast.Constant(module) for module in python_standard_library_modules])], keywords=[], ) - for python_stdlib_modules in stdlib_python.values() + for python_standard_library_modules in stdlib_python.values() ], ), lineno=None, @@ -95,4 +95,4 @@ def write_stdlibs_file(stdlib_python: dict[str, list[str]]) -> None: if __name__ == "__main__": - write_stdlibs_file(get_stdlib_modules()) + write_stdlibs_file(get_standard_library_modules()) diff --git a/tests/unit/test_core.py b/tests/unit/test_core.py index 0934038f..57d7cd8a 100644 --- a/tests/unit/test_core.py +++ b/tests/unit/test_core.py @@ -82,12 +82,12 @@ def test__get_local_modules( @pytest.mark.skipif(sys.version_info >= (3, 10), reason="mapping is only used for Python < 3.10") def test__get_stdlib_packages_without_stdlib_module_names() -> None: - assert Core._get_stdlib_modules() == STDLIBS_PYTHON[f"{sys.version_info[0]}{sys.version_info[1]}"] + assert Core._get_standard_library_modules() == STDLIBS_PYTHON[f"{sys.version_info[0]}{sys.version_info[1]}"] @pytest.mark.skipif(sys.version_info < (3, 10), reason="only Python >= 3.10 has sys.stdlib_module_names") def test__get_stdlib_packages_with_stdlib_module_names() -> None: - assert Core._get_stdlib_modules() == sys.stdlib_module_names # type: ignore[attr-defined, unused-ignore] + assert Core._get_standard_library_modules() == sys.stdlib_module_names # type: ignore[attr-defined, unused-ignore] @pytest.mark.parametrize( @@ -104,7 +104,7 @@ def test__get_stdlib_packages_with_stdlib_module_names() -> None: def test__get_stdlib_packages_with_stdlib_module_names_future_version(version_info: tuple[int | str, ...]) -> None: """Test that future versions of Python not yet tested on the CI will also work.""" with mock.patch("sys.version_info", (sys.version_info[0], sys.version_info[1] + 1, 0)): - assert Core._get_stdlib_modules() == sys.stdlib_module_names # type: ignore[attr-defined, unused-ignore] + assert Core._get_standard_library_modules() == sys.stdlib_module_names # type: ignore[attr-defined, unused-ignore] @pytest.mark.parametrize( @@ -126,7 +126,7 @@ def test__get_stdlib_packages_unsupported(version_info: tuple[int | str, ...]) - f"Python version {version_info[0]}.{version_info[1]} is not supported. Only versions >= 3.8 are supported." ), ): - Core._get_stdlib_modules() + Core._get_standard_library_modules() def test__exit_with_violations() -> None: diff --git a/tests/unit/violations/dep005_standard_library/test_finder.py b/tests/unit/violations/dep005_standard_library/test_finder.py index ef39a5be..526bbd2e 100644 --- a/tests/unit/violations/dep005_standard_library/test_finder.py +++ b/tests/unit/violations/dep005_standard_library/test_finder.py @@ -20,7 +20,7 @@ def test_simple() -> None: assert DEP005StandardLibraryDependencyFinder( imported_modules_with_locations=modules_locations, dependencies=dependencies, - stdlib_modules=frozenset(["asyncio"]), + standard_library_modules=frozenset(["asyncio"]), ).find() == [DEP005StandardLibraryDependencyViolation(dependency_asyncio, Location(Path("pyproject.toml")))] @@ -37,7 +37,7 @@ def test_simple_with_ignore() -> None: DEP005StandardLibraryDependencyFinder( imported_modules_with_locations=modules_locations, dependencies=dependencies, - stdlib_modules=frozenset(["asyncio"]), + standard_library_modules=frozenset(["asyncio"]), ignored_modules=("asyncio",), ).find() == [] From eeec2baab66411e86b146976a2775743a41c067c Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Sat, 13 Jul 2024 10:12:46 +0200 Subject: [PATCH 06/12] add more tests --- tests/unit/violations/dep001_missing/test_finder.py | 13 +++++++++++++ .../violations/dep003_transitive/test_finder.py | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tests/unit/violations/dep001_missing/test_finder.py b/tests/unit/violations/dep001_missing/test_finder.py index 0c970091..17ff04ac 100644 --- a/tests/unit/violations/dep001_missing/test_finder.py +++ b/tests/unit/violations/dep001_missing/test_finder.py @@ -44,6 +44,19 @@ def test_simple_with_ignore() -> None: assert DEP001MissingDependenciesFinder(modules_locations, dependencies, ignored_modules=("foobar",)).find() == [] +def test_simple_with_standard_library() -> None: + dependencies: list[Dependency] = [] + standard_library_modules = frozenset(["foobar"]) + modules_locations = [ + ModuleLocations( + ModuleBuilder("foobar", {}, standard_library_modules, dependencies).build(), + [Location(Path("foo.py"), 1, 2)], + ) + ] + + assert DEP001MissingDependenciesFinder(modules_locations, dependencies).find() == [] + + def test_no_error() -> None: """ This should run without an error, even though `foo` is not installed. diff --git a/tests/unit/violations/dep003_transitive/test_finder.py b/tests/unit/violations/dep003_transitive/test_finder.py index 31090fb0..de78235e 100644 --- a/tests/unit/violations/dep003_transitive/test_finder.py +++ b/tests/unit/violations/dep003_transitive/test_finder.py @@ -37,3 +37,16 @@ def test_simple_with_ignore() -> None: ] assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies, ignored_modules=("foobar",)).find() == [] + + +def test_simple_with_standard_library() -> None: + dependencies: list[Dependency] = [] + standard_library_modules = frozenset(["foobar"]) + modules_locations = [ + ModuleLocations( + ModuleBuilder("foobar", {"foo"}, standard_library_modules, dependencies).build(), + [Location(Path("foo.py"), 1, 2)], + ) + ] + + assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies).find() == [] From 5c4a6e55417fbc42e2c67334c784a802e5586d30 Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Sat, 13 Jul 2024 10:16:58 +0200 Subject: [PATCH 07/12] fix typing --- tests/unit/violations/dep001_missing/test_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/violations/dep001_missing/test_finder.py b/tests/unit/violations/dep001_missing/test_finder.py index 17ff04ac..45faf4a3 100644 --- a/tests/unit/violations/dep001_missing/test_finder.py +++ b/tests/unit/violations/dep001_missing/test_finder.py @@ -49,7 +49,7 @@ def test_simple_with_standard_library() -> None: standard_library_modules = frozenset(["foobar"]) modules_locations = [ ModuleLocations( - ModuleBuilder("foobar", {}, standard_library_modules, dependencies).build(), + ModuleBuilder("foobar", set(), standard_library_modules, dependencies).build(), [Location(Path("foo.py"), 1, 2)], ) ] From 46fbb78927a3bfc73acd9ca4530fdb9fa321beca Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 13 Jul 2024 14:40:31 +0200 Subject: [PATCH 08/12] better error message --- python/deptry/violations/dep005_standard_library/violation.py | 4 +++- tests/functional/cli/test_cli_pep_621.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/python/deptry/violations/dep005_standard_library/violation.py b/python/deptry/violations/dep005_standard_library/violation.py index c08d82b9..01387581 100644 --- a/python/deptry/violations/dep005_standard_library/violation.py +++ b/python/deptry/violations/dep005_standard_library/violation.py @@ -12,7 +12,9 @@ @dataclass class DEP005StandardLibraryDependencyViolation(Violation): error_code: ClassVar[str] = "DEP005" - error_template: ClassVar[str] = "'{name}' defined as a dependency but it's part of the standard library" + error_template: ClassVar[str] = ( + "'{name}' is defined as a dependency but it is included in the Python standard library." + ) issue: Dependency def get_error_message(self) -> str: diff --git a/tests/functional/cli/test_cli_pep_621.py b/tests/functional/cli/test_cli_pep_621.py index 0d1837b6..dc41e01b 100644 --- a/tests/functional/cli/test_cli_pep_621.py +++ b/tests/functional/cli/test_cli_pep_621.py @@ -50,7 +50,7 @@ def test_cli_with_pep_621(pip_venv_factory: PipVenvFactory) -> None: { "error": { "code": "DEP005", - "message": "'asyncio' defined as a dependency but it's part of the standard library", + "message": "'asyncio' is defined as a dependency but it is included in the Python standard library.", }, "module": "asyncio", "location": {"file": "pyproject.toml", "line": None, "column": None}, From e13c054ca3bf113674ac252ffb317650b0dafbc2 Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Fri, 19 Jul 2024 13:52:40 +0200 Subject: [PATCH 09/12] Update python/deptry/violations/dep005_standard_library/finder.py Co-authored-by: Mathieu Kniewallner --- python/deptry/violations/dep005_standard_library/finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py index dde56d50..7c2cc619 100644 --- a/python/deptry/violations/dep005_standard_library/finder.py +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -13,7 +13,7 @@ from deptry.violations import Violation -class DEP005StandardLibraryDependencyFinder(ViolationsFinder): +class DEP005StandardLibraryDependenciesFinder(ViolationsFinder): """ Finds dependencies that are part of the standard library but are defined as dependencies. """ From 541cba954a39428387b4605682bde5a04a327554 Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Fri, 19 Jul 2024 13:52:51 +0200 Subject: [PATCH 10/12] Update python/deptry/violations/finder.py Co-authored-by: Mathieu Kniewallner --- python/deptry/violations/finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/deptry/violations/finder.py b/python/deptry/violations/finder.py index 663c3f7e..9ff3c6e7 100644 --- a/python/deptry/violations/finder.py +++ b/python/deptry/violations/finder.py @@ -53,7 +53,7 @@ def find_violations( DEP005StandardLibraryDependencyFinder( imported_modules_with_locations=imported_modules_with_locations, dependencies=dependencies, - ignored_modules=per_rule_ignores.get(violation_finder.violation.error_code, ()), + ignored_modules=per_rule_ignores.get(DEP005StandardLibraryDependencyFinder.violation.error_code, ()), standard_library_modules=standard_library_modules, ).find() ) From 8cc3542673e366e88ef26eb2c88199c70cdb446c Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Fri, 19 Jul 2024 14:05:45 +0200 Subject: [PATCH 11/12] fix --- python/deptry/violations/__init__.py | 4 ++-- python/deptry/violations/base.py | 16 ++++++---------- .../deptry/violations/dep001_missing/finder.py | 2 ++ .../deptry/violations/dep002_unused/finder.py | 2 ++ .../violations/dep003_transitive/finder.py | 2 ++ .../violations/dep004_misplaced_dev/finder.py | 3 +++ .../dep005_standard_library/finder.py | 14 ++------------ python/deptry/violations/finder.py | 17 +++-------------- .../violations/dep001_missing/test_finder.py | 18 ++++++++++++------ .../violations/dep002_unused/test_finder.py | 11 +++++++---- .../dep003_transitive/test_finder.py | 11 ++++++++--- .../dep004_misplaced_dev/test_finder.py | 4 ++-- .../dep005_standard_library/test_finder.py | 6 +++--- 13 files changed, 54 insertions(+), 56 deletions(-) diff --git a/python/deptry/violations/__init__.py b/python/deptry/violations/__init__.py index a9b328c1..b10cfcc4 100644 --- a/python/deptry/violations/__init__.py +++ b/python/deptry/violations/__init__.py @@ -9,7 +9,7 @@ from deptry.violations.dep003_transitive.violation import DEP003TransitiveDependencyViolation from deptry.violations.dep004_misplaced_dev.finder import DEP004MisplacedDevDependenciesFinder from deptry.violations.dep004_misplaced_dev.violation import DEP004MisplacedDevDependencyViolation -from deptry.violations.dep005_standard_library.finder import DEP005StandardLibraryDependencyFinder +from deptry.violations.dep005_standard_library.finder import DEP005StandardLibraryDependenciesFinder from deptry.violations.dep005_standard_library.violation import DEP005StandardLibraryDependencyViolation __all__ = ( @@ -22,7 +22,7 @@ "DEP002UnusedDependenciesFinder", "DEP003TransitiveDependenciesFinder", "DEP004MisplacedDevDependenciesFinder", - "DEP005StandardLibraryDependencyFinder", + "DEP005StandardLibraryDependenciesFinder", "Violation", "ViolationsFinder", ) diff --git a/python/deptry/violations/base.py b/python/deptry/violations/base.py index 3b1afae4..bbf50322 100644 --- a/python/deptry/violations/base.py +++ b/python/deptry/violations/base.py @@ -10,6 +10,7 @@ from deptry.module import Module, ModuleLocations +@dataclass class ViolationsFinder(ABC): """Base class for all issues finders. @@ -22,19 +23,14 @@ class ViolationsFinder(ABC): dependencies: A list of Dependency objects representing the project's dependencies. ignored_modules: A tuple of module names to ignore when scanning for issues. Defaults to an empty tuple. + standard_library_modules: A set of modules that are part of the standard library """ violation: ClassVar[type[Violation]] - - def __init__( - self, - imported_modules_with_locations: list[ModuleLocations], - dependencies: list[Dependency], - ignored_modules: tuple[str, ...] = (), - ): - self.imported_modules_with_locations = imported_modules_with_locations - self.dependencies = dependencies - self.ignored_modules = ignored_modules + imported_modules_with_locations: list[ModuleLocations] + dependencies: list[Dependency] + standard_library_modules: frozenset[str] + ignored_modules: tuple[str, ...] = () @abstractmethod def find(self) -> list[Violation]: diff --git a/python/deptry/violations/dep001_missing/finder.py b/python/deptry/violations/dep001_missing/finder.py index 39db704d..893b801a 100644 --- a/python/deptry/violations/dep001_missing/finder.py +++ b/python/deptry/violations/dep001_missing/finder.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.violations.base import ViolationsFinder @@ -11,6 +12,7 @@ from deptry.violations.base import Violation +@dataclass class DEP001MissingDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which ones are missing. diff --git a/python/deptry/violations/dep002_unused/finder.py b/python/deptry/violations/dep002_unused/finder.py index 62340d53..f364e39a 100644 --- a/python/deptry/violations/dep002_unused/finder.py +++ b/python/deptry/violations/dep002_unused/finder.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.imports.location import Location @@ -12,6 +13,7 @@ from deptry.violations import Violation +@dataclass class DEP002UnusedDependenciesFinder(ViolationsFinder): """ Finds unused dependencies by comparing a list of imported modules to a list of project dependencies. diff --git a/python/deptry/violations/dep003_transitive/finder.py b/python/deptry/violations/dep003_transitive/finder.py index 8102d8b7..d103a102 100644 --- a/python/deptry/violations/dep003_transitive/finder.py +++ b/python/deptry/violations/dep003_transitive/finder.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.violations.base import ViolationsFinder @@ -11,6 +12,7 @@ from deptry.violations import Violation +@dataclass class DEP003TransitiveDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which ones are transitive. diff --git a/python/deptry/violations/dep004_misplaced_dev/finder.py b/python/deptry/violations/dep004_misplaced_dev/finder.py index bb0e8350..62af53d3 100644 --- a/python/deptry/violations/dep004_misplaced_dev/finder.py +++ b/python/deptry/violations/dep004_misplaced_dev/finder.py @@ -10,7 +10,10 @@ from deptry.module import Module from deptry.violations import Violation +from dataclasses import dataclass + +@dataclass class DEP004MisplacedDevDependenciesFinder(ViolationsFinder): """ Given a list of imported modules and a list of project dependencies, determine which development dependencies diff --git a/python/deptry/violations/dep005_standard_library/finder.py b/python/deptry/violations/dep005_standard_library/finder.py index 7c2cc619..94e68f0a 100644 --- a/python/deptry/violations/dep005_standard_library/finder.py +++ b/python/deptry/violations/dep005_standard_library/finder.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +from dataclasses import dataclass from typing import TYPE_CHECKING from deptry.imports.location import Location @@ -8,11 +9,10 @@ from deptry.violations.dep005_standard_library.violation import DEP005StandardLibraryDependencyViolation if TYPE_CHECKING: - from deptry.dependency import Dependency - from deptry.module import ModuleLocations from deptry.violations import Violation +@dataclass class DEP005StandardLibraryDependenciesFinder(ViolationsFinder): """ Finds dependencies that are part of the standard library but are defined as dependencies. @@ -20,16 +20,6 @@ class DEP005StandardLibraryDependenciesFinder(ViolationsFinder): violation = DEP005StandardLibraryDependencyViolation - def __init__( - self, - imported_modules_with_locations: list[ModuleLocations], - dependencies: list[Dependency], - standard_library_modules: frozenset[str], - ignored_modules: tuple[str, ...] = (), - ): - super().__init__(imported_modules_with_locations, dependencies, ignored_modules) - self.standard_library_modules = standard_library_modules - def find(self) -> list[Violation]: logging.debug("\nScanning for dependencies that are part of the standard library...") stdlib_violations: list[Violation] = [] diff --git a/python/deptry/violations/finder.py b/python/deptry/violations/finder.py index 9ff3c6e7..6311f9d1 100644 --- a/python/deptry/violations/finder.py +++ b/python/deptry/violations/finder.py @@ -8,7 +8,7 @@ DEP002UnusedDependenciesFinder, DEP003TransitiveDependenciesFinder, DEP004MisplacedDevDependenciesFinder, - DEP005StandardLibraryDependencyFinder, + DEP005StandardLibraryDependenciesFinder, ) if TYPE_CHECKING: @@ -24,6 +24,7 @@ DEP002UnusedDependenciesFinder, DEP003TransitiveDependenciesFinder, DEP004MisplacedDevDependenciesFinder, + DEP005StandardLibraryDependenciesFinder, ) @@ -43,21 +44,9 @@ def find_violations( imported_modules_with_locations=imported_modules_with_locations, dependencies=dependencies, ignored_modules=per_rule_ignores.get(violation_finder.violation.error_code, ()), + standard_library_modules=standard_library_modules, ).find() ) - - # Since DEP005StandardLibraryDependencyFinder has a different constructor than the other 4 classes, - # we handle it separately. - if DEP005StandardLibraryDependencyFinder.violation.error_code not in ignore: - violations.extend( - DEP005StandardLibraryDependencyFinder( - imported_modules_with_locations=imported_modules_with_locations, - dependencies=dependencies, - ignored_modules=per_rule_ignores.get(DEP005StandardLibraryDependencyFinder.violation.error_code, ()), - standard_library_modules=standard_library_modules, - ).find() - ) - return _get_sorted_violations(violations) diff --git a/tests/unit/violations/dep001_missing/test_finder.py b/tests/unit/violations/dep001_missing/test_finder.py index 45faf4a3..b46ee297 100644 --- a/tests/unit/violations/dep001_missing/test_finder.py +++ b/tests/unit/violations/dep001_missing/test_finder.py @@ -16,7 +16,7 @@ def test_simple() -> None: modules_locations = [ModuleLocations(module_foobar, module_foobar_locations)] - assert DEP001MissingDependenciesFinder(modules_locations, dependencies).find() == [ + assert DEP001MissingDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [ DEP001MissingDependencyViolation(module_foobar, location) for location in module_foobar_locations ] @@ -30,7 +30,7 @@ def test_local_module() -> None: ) ] - assert DEP001MissingDependenciesFinder(modules_locations, dependencies).find() == [] + assert DEP001MissingDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [] def test_simple_with_ignore() -> None: @@ -41,7 +41,12 @@ def test_simple_with_ignore() -> None: ) ] - assert DEP001MissingDependenciesFinder(modules_locations, dependencies, ignored_modules=("foobar",)).find() == [] + assert ( + DEP001MissingDependenciesFinder( + modules_locations, dependencies, frozenset(), ignored_modules=("foobar",) + ).find() + == [] + ) def test_simple_with_standard_library() -> None: @@ -54,7 +59,7 @@ def test_simple_with_standard_library() -> None: ) ] - assert DEP001MissingDependenciesFinder(modules_locations, dependencies).find() == [] + assert DEP001MissingDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [] def test_no_error() -> None: @@ -65,8 +70,9 @@ def test_no_error() -> None: dependencies = [Dependency("foo", Path("pyproject.toml"))] modules_locations = [ ModuleLocations( - ModuleBuilder("foo", {"bar"}, frozenset(), dependencies).build(), [Location(Path("foo.py"), 1, 2)] + ModuleBuilder("foo", {"bar"}, frozenset(), dependencies, frozenset()).build(), + [Location(Path("foo.py"), 1, 2)], ) ] - assert DEP001MissingDependenciesFinder(modules_locations, dependencies).find() == [] + assert DEP001MissingDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [] diff --git a/tests/unit/violations/dep002_unused/test_finder.py b/tests/unit/violations/dep002_unused/test_finder.py index 14b3c4aa..284a5697 100644 --- a/tests/unit/violations/dep002_unused/test_finder.py +++ b/tests/unit/violations/dep002_unused/test_finder.py @@ -17,7 +17,7 @@ def test_simple() -> None: ) ] - assert DEP002UnusedDependenciesFinder(modules_locations, dependencies).find() == [ + assert DEP002UnusedDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [ DEP002UnusedDependencyViolation(dependency_toml, Location(Path("pyproject.toml"))) ] @@ -30,7 +30,10 @@ def test_simple_with_ignore() -> None: ) ] - assert DEP002UnusedDependenciesFinder(modules_locations, dependencies, ignored_modules=("click",)).find() == [] + assert ( + DEP002UnusedDependenciesFinder(modules_locations, dependencies, frozenset(), ignored_modules=("click",)).find() + == [] + ) def test_top_level() -> None: @@ -45,7 +48,7 @@ def test_top_level() -> None: ) ] - deps = DEP002UnusedDependenciesFinder(modules_locations, dependencies).find() + deps = DEP002UnusedDependenciesFinder(modules_locations, dependencies, frozenset()).find() assert deps == [] @@ -61,4 +64,4 @@ def test_without_top_level() -> None: ) ] - assert DEP002UnusedDependenciesFinder(modules_locations, dependencies).find() == [] + assert DEP002UnusedDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [] diff --git a/tests/unit/violations/dep003_transitive/test_finder.py b/tests/unit/violations/dep003_transitive/test_finder.py index de78235e..3c21cec9 100644 --- a/tests/unit/violations/dep003_transitive/test_finder.py +++ b/tests/unit/violations/dep003_transitive/test_finder.py @@ -23,7 +23,7 @@ def test_simple() -> None: modules_locations = [ModuleLocations(module_platformdirs, module_platformdirs_locations)] - assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies).find() == [ + assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [ DEP003TransitiveDependencyViolation(module_platformdirs, location) for location in module_platformdirs_locations ] @@ -36,7 +36,12 @@ def test_simple_with_ignore() -> None: ) ] - assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies, ignored_modules=("foobar",)).find() == [] + assert ( + DEP003TransitiveDependenciesFinder( + modules_locations, dependencies, frozenset(), ignored_modules=("foobar",) + ).find() + == [] + ) def test_simple_with_standard_library() -> None: @@ -49,4 +54,4 @@ def test_simple_with_standard_library() -> None: ) ] - assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies).find() == [] + assert DEP003TransitiveDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [] diff --git a/tests/unit/violations/dep004_misplaced_dev/test_finder.py b/tests/unit/violations/dep004_misplaced_dev/test_finder.py index 6c16607b..be79f501 100644 --- a/tests/unit/violations/dep004_misplaced_dev/test_finder.py +++ b/tests/unit/violations/dep004_misplaced_dev/test_finder.py @@ -17,7 +17,7 @@ def test_simple() -> None: modules_locations = [ModuleLocations(module_foo, module_foo_locations)] - assert DEP004MisplacedDevDependenciesFinder(modules_locations, dependencies).find() == [ + assert DEP004MisplacedDevDependenciesFinder(modules_locations, dependencies, frozenset()).find() == [ DEP004MisplacedDevDependencyViolation(module_foo, location) for location in module_foo_locations ] @@ -37,4 +37,4 @@ def test_regular_and_dev_dependency() -> None: modules_locations = [ModuleLocations(module_foo, module_foo_locations)] - assert not DEP004MisplacedDevDependenciesFinder(modules_locations, dependencies).find() + assert not DEP004MisplacedDevDependenciesFinder(modules_locations, dependencies, frozenset()).find() diff --git a/tests/unit/violations/dep005_standard_library/test_finder.py b/tests/unit/violations/dep005_standard_library/test_finder.py index 526bbd2e..6c4fe9c6 100644 --- a/tests/unit/violations/dep005_standard_library/test_finder.py +++ b/tests/unit/violations/dep005_standard_library/test_finder.py @@ -5,7 +5,7 @@ from deptry.dependency import Dependency from deptry.imports.location import Location from deptry.module import ModuleBuilder, ModuleLocations -from deptry.violations import DEP005StandardLibraryDependencyFinder, DEP005StandardLibraryDependencyViolation +from deptry.violations import DEP005StandardLibraryDependenciesFinder, DEP005StandardLibraryDependencyViolation def test_simple() -> None: @@ -17,7 +17,7 @@ def test_simple() -> None: ) ] - assert DEP005StandardLibraryDependencyFinder( + assert DEP005StandardLibraryDependenciesFinder( imported_modules_with_locations=modules_locations, dependencies=dependencies, standard_library_modules=frozenset(["asyncio"]), @@ -34,7 +34,7 @@ def test_simple_with_ignore() -> None: ] assert ( - DEP005StandardLibraryDependencyFinder( + DEP005StandardLibraryDependenciesFinder( imported_modules_with_locations=modules_locations, dependencies=dependencies, standard_library_modules=frozenset(["asyncio"]), From 453d3ac7a3fc03070ac27301b4827e775fa04d1d Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Fri, 19 Jul 2024 14:27:52 +0200 Subject: [PATCH 12/12] hotfix --- tests/unit/violations/dep001_missing/test_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/violations/dep001_missing/test_finder.py b/tests/unit/violations/dep001_missing/test_finder.py index b46ee297..dfbdfcb2 100644 --- a/tests/unit/violations/dep001_missing/test_finder.py +++ b/tests/unit/violations/dep001_missing/test_finder.py @@ -70,7 +70,7 @@ def test_no_error() -> None: dependencies = [Dependency("foo", Path("pyproject.toml"))] modules_locations = [ ModuleLocations( - ModuleBuilder("foo", {"bar"}, frozenset(), dependencies, frozenset()).build(), + ModuleBuilder("foo", {"bar"}, frozenset(), dependencies).build(), [Location(Path("foo.py"), 1, 2)], ) ]