diff --git a/deptry/core.py b/deptry/core.py index 6a0f25fe..70cb0948 100644 --- a/deptry/core.py +++ b/deptry/core.py @@ -28,7 +28,7 @@ from deptry.dependency import Dependency from deptry.dependency_getter.base import DependenciesExtract from deptry.module import Module - from deptry.violation import Violation + from deptry.violations import Violation @dataclass diff --git a/deptry/issues_finder/base.py b/deptry/issues_finder/base.py index 025aae0c..5b4afaf9 100644 --- a/deptry/issues_finder/base.py +++ b/deptry/issues_finder/base.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from deptry.dependency import Dependency from deptry.module import Module - from deptry.violation import Violation + from deptry.violations import Violation @dataclass diff --git a/deptry/issues_finder/misplaced_dev.py b/deptry/issues_finder/misplaced_dev.py index 54e083ae..716ae697 100644 --- a/deptry/issues_finder/misplaced_dev.py +++ b/deptry/issues_finder/misplaced_dev.py @@ -5,10 +5,11 @@ from typing import TYPE_CHECKING from deptry.issues_finder.base import IssuesFinder -from deptry.violation import Violation +from deptry.violations import MisplacedDevDependencyViolation if TYPE_CHECKING: from deptry.module import Module + from deptry.violations import Violation @dataclass @@ -27,14 +28,14 @@ def find(self) -> list[Violation]: 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...") - misplaced_dev_dependencies = [] + misplaced_dev_dependencies: list[Violation] = [] for module in self.imported_modules: logging.debug(f"Scanning module {module.name}...") corresponding_package_name = self._get_package_name(module) if corresponding_package_name and self._is_development_dependency(module, corresponding_package_name): - misplaced_dev_dependencies.append(Violation(self.__class__, module)) + misplaced_dev_dependencies.append(MisplacedDevDependencyViolation(module)) return misplaced_dev_dependencies diff --git a/deptry/issues_finder/missing.py b/deptry/issues_finder/missing.py index 8026edd1..515d9220 100644 --- a/deptry/issues_finder/missing.py +++ b/deptry/issues_finder/missing.py @@ -5,10 +5,11 @@ from typing import TYPE_CHECKING from deptry.issues_finder.base import IssuesFinder -from deptry.violation import Violation +from deptry.violations import MissingDependencyViolation if TYPE_CHECKING: from deptry.module import Module + from deptry.violations import Violation @dataclass @@ -19,13 +20,13 @@ class MissingDependenciesFinder(IssuesFinder): def find(self) -> list[Violation]: logging.debug("\nScanning for missing dependencies...") - missing_dependencies = [] + missing_dependencies: list[Violation] = [] for module in self.imported_modules: logging.debug(f"Scanning module {module.name}...") if self._is_missing(module): - missing_dependencies.append(Violation(self.__class__, module)) + missing_dependencies.append(MissingDependencyViolation(module)) return missing_dependencies diff --git a/deptry/issues_finder/obsolete.py b/deptry/issues_finder/obsolete.py index 49e67240..b46185e4 100644 --- a/deptry/issues_finder/obsolete.py +++ b/deptry/issues_finder/obsolete.py @@ -5,10 +5,11 @@ from typing import TYPE_CHECKING from deptry.issues_finder.base import IssuesFinder -from deptry.violation import Violation +from deptry.violations import ObsoleteDependencyViolation if TYPE_CHECKING: from deptry.dependency import Dependency + from deptry.violations import Violation @dataclass @@ -25,13 +26,13 @@ class ObsoleteDependenciesFinder(IssuesFinder): def find(self) -> list[Violation]: logging.debug("\nScanning for obsolete dependencies...") - obsolete_dependencies = [] + obsolete_dependencies: list[Violation] = [] for dependency in self.dependencies: logging.debug(f"Scanning module {dependency.name}...") if self._is_obsolete(dependency): - obsolete_dependencies.append(Violation(self.__class__, dependency)) + obsolete_dependencies.append(ObsoleteDependencyViolation(dependency)) return obsolete_dependencies diff --git a/deptry/issues_finder/transitive.py b/deptry/issues_finder/transitive.py index a8301c47..559bb3da 100644 --- a/deptry/issues_finder/transitive.py +++ b/deptry/issues_finder/transitive.py @@ -5,10 +5,11 @@ from typing import TYPE_CHECKING from deptry.issues_finder.base import IssuesFinder -from deptry.violation import Violation +from deptry.violations import TransitiveDependencyViolation if TYPE_CHECKING: from deptry.module import Module + from deptry.violations import Violation @dataclass @@ -26,14 +27,14 @@ class TransitiveDependenciesFinder(IssuesFinder): def find(self) -> list[Violation]: logging.debug("\nScanning for transitive dependencies...") - transitive_dependencies = [] + transitive_dependencies: list[Violation] = [] for module in self.imported_modules: logging.debug(f"Scanning module {module.name}...") if self._is_transitive(module): # `self._is_transitive` only returns `True` if the package is not None. - transitive_dependencies.append(Violation(self.__class__, module)) + transitive_dependencies.append(TransitiveDependencyViolation(module)) return transitive_dependencies diff --git a/deptry/reporters/base.py b/deptry/reporters/base.py index 179de212..8e8db7db 100644 --- a/deptry/reporters/base.py +++ b/deptry/reporters/base.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from deptry.violation import Violation + from deptry.violations import Violation @dataclass diff --git a/deptry/reporters/json.py b/deptry/reporters/json.py index c5963467..8a5f18f2 100644 --- a/deptry/reporters/json.py +++ b/deptry/reporters/json.py @@ -3,9 +3,8 @@ import json from dataclasses import dataclass -from deptry.issues_finder.transitive import TransitiveDependenciesFinder -from deptry.module import Module from deptry.reporters.base import Reporter +from deptry.violations import TransitiveDependencyViolation @dataclass @@ -19,7 +18,7 @@ def report(self) -> None: output[issue_type] = [ ( violation.issue.package - if isinstance(violation.issue, Module) and violation.issue_type is TransitiveDependenciesFinder + if isinstance(violation, TransitiveDependencyViolation) else violation.issue.name ) for violation in violations diff --git a/deptry/reporters/text.py b/deptry/reporters/text.py index de7e4af2..bb588c15 100644 --- a/deptry/reporters/text.py +++ b/deptry/reporters/text.py @@ -8,7 +8,7 @@ from deptry.reporters.base import Reporter if TYPE_CHECKING: - from deptry.violation import Violation + from deptry.violations import Violation @dataclass diff --git a/deptry/violations/__init__.py b/deptry/violations/__init__.py new file mode 100644 index 00000000..100b7faa --- /dev/null +++ b/deptry/violations/__init__.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from deptry.violations.base import Violation +from deptry.violations.misplaced_dev import MisplacedDevDependencyViolation +from deptry.violations.missing import MissingDependencyViolation +from deptry.violations.obsolete import ObsoleteDependencyViolation +from deptry.violations.transitive import TransitiveDependencyViolation + +__all__ = ( + "MisplacedDevDependencyViolation", + "MissingDependencyViolation", + "ObsoleteDependencyViolation", + "TransitiveDependencyViolation", + "Violation", +) diff --git a/deptry/violation.py b/deptry/violations/base.py similarity index 69% rename from deptry/violation.py rename to deptry/violations/base.py index 89f6875e..798bd8b7 100644 --- a/deptry/violation.py +++ b/deptry/violations/base.py @@ -1,15 +1,14 @@ from __future__ import annotations +from abc import ABC from dataclasses import dataclass from typing import TYPE_CHECKING if TYPE_CHECKING: from deptry.dependency import Dependency - from deptry.issues_finder.base import IssuesFinder from deptry.module import Module @dataclass -class Violation: - issue_type: type[IssuesFinder] +class Violation(ABC): issue: Dependency | Module diff --git a/deptry/violations/misplaced_dev.py b/deptry/violations/misplaced_dev.py new file mode 100644 index 00000000..be61d169 --- /dev/null +++ b/deptry/violations/misplaced_dev.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +from deptry.violations import Violation + +if TYPE_CHECKING: + from deptry.module import Module + + +@dataclass +class MisplacedDevDependencyViolation(Violation): + issue: Module diff --git a/deptry/violations/missing.py b/deptry/violations/missing.py new file mode 100644 index 00000000..6dcb5f02 --- /dev/null +++ b/deptry/violations/missing.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +from deptry.violations import Violation + +if TYPE_CHECKING: + from deptry.module import Module + + +@dataclass +class MissingDependencyViolation(Violation): + issue: Module diff --git a/deptry/violations/obsolete.py b/deptry/violations/obsolete.py new file mode 100644 index 00000000..64dd298b --- /dev/null +++ b/deptry/violations/obsolete.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +from deptry.violations import Violation + +if TYPE_CHECKING: + from deptry.dependency import Dependency + + +@dataclass +class ObsoleteDependencyViolation(Violation): + issue: Dependency diff --git a/deptry/violations/transitive.py b/deptry/violations/transitive.py new file mode 100644 index 00000000..f4c4adf3 --- /dev/null +++ b/deptry/violations/transitive.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +from deptry.violations import Violation + +if TYPE_CHECKING: + from deptry.module import Module + + +@dataclass +class TransitiveDependencyViolation(Violation): + issue: Module diff --git a/tests/unit/issues_finder/test_misplaced_dev.py b/tests/unit/issues_finder/test_misplaced_dev.py index d243b9c8..699324fe 100644 --- a/tests/unit/issues_finder/test_misplaced_dev.py +++ b/tests/unit/issues_finder/test_misplaced_dev.py @@ -5,7 +5,7 @@ from deptry.dependency import Dependency from deptry.issues_finder.misplaced_dev import MisplacedDevDependenciesFinder from deptry.module import Module -from deptry.violation import Violation +from deptry.violations import MisplacedDevDependencyViolation def test_simple() -> None: @@ -15,4 +15,4 @@ def test_simple() -> None: deps = MisplacedDevDependenciesFinder(imported_modules=modules, dependencies=dependencies).find() - assert deps == [Violation(MisplacedDevDependenciesFinder, module_foo)] + assert deps == [MisplacedDevDependencyViolation(module_foo)] diff --git a/tests/unit/issues_finder/test_missing.py b/tests/unit/issues_finder/test_missing.py index fcc1be82..79c1ad7e 100644 --- a/tests/unit/issues_finder/test_missing.py +++ b/tests/unit/issues_finder/test_missing.py @@ -5,7 +5,7 @@ from deptry.dependency import Dependency from deptry.issues_finder.missing import MissingDependenciesFinder from deptry.module import ModuleBuilder -from deptry.violation import Violation +from deptry.violations import MissingDependencyViolation def test_simple() -> None: @@ -15,7 +15,7 @@ def test_simple() -> None: deps = MissingDependenciesFinder(imported_modules=modules, dependencies=dependencies).find() - assert deps == [Violation(MissingDependenciesFinder, module_foobar)] + assert deps == [MissingDependencyViolation(module_foobar)] def test_local_module() -> None: diff --git a/tests/unit/issues_finder/test_obsolete.py b/tests/unit/issues_finder/test_obsolete.py index cd578738..16c12637 100644 --- a/tests/unit/issues_finder/test_obsolete.py +++ b/tests/unit/issues_finder/test_obsolete.py @@ -5,7 +5,7 @@ from deptry.dependency import Dependency from deptry.issues_finder.obsolete import ObsoleteDependenciesFinder from deptry.module import ModuleBuilder -from deptry.violation import Violation +from deptry.violations import ObsoleteDependencyViolation def test_simple() -> None: @@ -15,7 +15,7 @@ def test_simple() -> None: deps = ObsoleteDependenciesFinder(imported_modules=modules, dependencies=dependencies).find() - assert deps == [Violation(ObsoleteDependenciesFinder, dependency_toml)] + assert deps == [ObsoleteDependencyViolation(dependency_toml)] def test_simple_with_ignore() -> None: diff --git a/tests/unit/issues_finder/test_transitive.py b/tests/unit/issues_finder/test_transitive.py index 36c61648..5b335e4b 100644 --- a/tests/unit/issues_finder/test_transitive.py +++ b/tests/unit/issues_finder/test_transitive.py @@ -4,7 +4,7 @@ from deptry.issues_finder.transitive import TransitiveDependenciesFinder from deptry.module import ModuleBuilder -from deptry.violation import Violation +from deptry.violations import TransitiveDependencyViolation if TYPE_CHECKING: from deptry.dependency import Dependency @@ -20,7 +20,7 @@ def test_simple() -> None: deps = TransitiveDependenciesFinder(imported_modules=modules, dependencies=dependencies).find() - assert deps == [Violation(TransitiveDependenciesFinder, module_platformdirs)] + assert deps == [TransitiveDependencyViolation(module_platformdirs)] def test_simple_with_ignore() -> None: diff --git a/tests/unit/reporters/test_json_reporter.py b/tests/unit/reporters/test_json_reporter.py index d5a38e5f..d63e6b46 100644 --- a/tests/unit/reporters/test_json_reporter.py +++ b/tests/unit/reporters/test_json_reporter.py @@ -4,13 +4,14 @@ from pathlib import Path from deptry.dependency import Dependency -from deptry.issues_finder.misplaced_dev import MisplacedDevDependenciesFinder -from deptry.issues_finder.missing import MissingDependenciesFinder -from deptry.issues_finder.obsolete import ObsoleteDependenciesFinder -from deptry.issues_finder.transitive import TransitiveDependenciesFinder from deptry.module import Module from deptry.reporters import JSONReporter -from deptry.violation import Violation +from deptry.violations import ( + MisplacedDevDependencyViolation, + MissingDependencyViolation, + ObsoleteDependencyViolation, + TransitiveDependencyViolation, +) from tests.utils import run_within_dir @@ -18,10 +19,10 @@ def test_simple(tmp_path: Path) -> None: with run_within_dir(tmp_path): JSONReporter( { - "missing": [Violation(MissingDependenciesFinder, Module("foo", package="foo_package"))], - "obsolete": [Violation(ObsoleteDependenciesFinder, Dependency("foo", Path("pyproject.toml")))], - "transitive": [Violation(TransitiveDependenciesFinder, Module("foo", package="foo_package"))], - "misplaced_dev": [Violation(MisplacedDevDependenciesFinder, Module("foo", package="foo_package"))], + "missing": [MissingDependencyViolation(Module("foo", package="foo_package"))], + "obsolete": [ObsoleteDependencyViolation(Dependency("foo", Path("pyproject.toml")))], + "transitive": [TransitiveDependencyViolation(Module("foo", package="foo_package"))], + "misplaced_dev": [MisplacedDevDependencyViolation(Module("foo", package="foo_package"))], }, "output.json", ).report() diff --git a/tests/unit/reporters/test_text_reporter.py b/tests/unit/reporters/test_text_reporter.py index 574702ed..5d97428b 100644 --- a/tests/unit/reporters/test_text_reporter.py +++ b/tests/unit/reporters/test_text_reporter.py @@ -5,25 +5,28 @@ from typing import TYPE_CHECKING from deptry.dependency import Dependency -from deptry.issues_finder.misplaced_dev import MisplacedDevDependenciesFinder -from deptry.issues_finder.missing import MissingDependenciesFinder -from deptry.issues_finder.obsolete import ObsoleteDependenciesFinder -from deptry.issues_finder.transitive import TransitiveDependenciesFinder from deptry.module import Module from deptry.reporters import TextReporter -from deptry.violation import Violation +from deptry.violations import ( + MisplacedDevDependencyViolation, + MissingDependencyViolation, + ObsoleteDependencyViolation, + TransitiveDependencyViolation, +) if TYPE_CHECKING: from _pytest.logging import LogCaptureFixture + from deptry.violations import Violation + def test_logging_number_multiple(caplog: LogCaptureFixture) -> None: with caplog.at_level(logging.INFO): - violations = { - "missing": [Violation(MissingDependenciesFinder, Module("foo", package="foo_package"))], - "obsolete": [Violation(ObsoleteDependenciesFinder, Dependency("foo", Path("pyproject.toml")))], - "transitive": [Violation(TransitiveDependenciesFinder, Module("foo", package="foo_package"))], - "misplaced_dev": [Violation(MisplacedDevDependenciesFinder, Module("foo", package="foo_package"))], + violations: dict[str, list[Violation]] = { + "missing": [MissingDependencyViolation(Module("foo", package="foo_package"))], + "obsolete": [ObsoleteDependencyViolation(Dependency("foo", Path("pyproject.toml")))], + "transitive": [TransitiveDependencyViolation(Module("foo", package="foo_package"))], + "misplaced_dev": [MisplacedDevDependencyViolation(Module("foo", package="foo_package"))], } TextReporter(violations).report() @@ -37,7 +40,9 @@ def test_logging_number_multiple(caplog: LogCaptureFixture) -> None: def test_logging_number_single(caplog: LogCaptureFixture) -> None: with caplog.at_level(logging.INFO): - violations = {"missing": [Violation(MissingDependenciesFinder, Module("foo", package="foo_package"))]} + violations: dict[str, list[Violation]] = { + "missing": [MissingDependencyViolation(Module("foo", package="foo_package"))] + } TextReporter(violations).report() assert "There was 1 dependency issue found" in caplog.text diff --git a/tests/unit/test_core.py b/tests/unit/test_core.py index d4de3f32..4880449a 100644 --- a/tests/unit/test_core.py +++ b/tests/unit/test_core.py @@ -3,6 +3,7 @@ import re import sys from pathlib import Path +from typing import TYPE_CHECKING from unittest import mock import pytest @@ -10,15 +11,19 @@ from deptry.core import Core from deptry.dependency import Dependency from deptry.exceptions import UnsupportedPythonVersionError -from deptry.issues_finder.misplaced_dev import MisplacedDevDependenciesFinder -from deptry.issues_finder.missing import MissingDependenciesFinder -from deptry.issues_finder.obsolete import ObsoleteDependenciesFinder -from deptry.issues_finder.transitive import TransitiveDependenciesFinder from deptry.module import Module from deptry.stdlibs import STDLIBS_PYTHON -from deptry.violation import Violation +from deptry.violations import ( + MisplacedDevDependencyViolation, + MissingDependencyViolation, + ObsoleteDependencyViolation, + TransitiveDependencyViolation, +) from tests.utils import create_files, run_within_dir +if TYPE_CHECKING: + from deptry.violations import Violation + @pytest.mark.parametrize( ("known_first_party", "root_suffix", "expected"), @@ -132,11 +137,11 @@ def test__get_stdlib_packages_unsupported(version_info: tuple[int | str, ...]) - def test__exit_with_violations() -> None: - violations = { - "missing": [Violation(MissingDependenciesFinder, Module("foo"))], - "obsolete": [Violation(ObsoleteDependenciesFinder, Dependency("foo", Path("pyproject.toml")))], - "transitive": [Violation(TransitiveDependenciesFinder, Module("foo"))], - "misplaced_dev": [Violation(MisplacedDevDependenciesFinder, Module("foo"))], + violations: dict[str, list[Violation]] = { + "missing": [MissingDependencyViolation(Module("foo"))], + "obsolete": [ObsoleteDependencyViolation(Dependency("foo", Path("pyproject.toml")))], + "transitive": [TransitiveDependencyViolation(Module("foo"))], + "misplaced_dev": [MisplacedDevDependencyViolation(Module("foo"))], } with pytest.raises(SystemExit) as e: Core._exit(violations)