From 082084502e56acc4b363175657fe78799c377ce2 Mon Sep 17 00:00:00 2001 From: Mathieu Kniewallner Date: Fri, 5 Jul 2024 09:01:48 +0200 Subject: [PATCH] fix(core): use `rglob` to guess local Python modules (#753) * test: add namespace package test case * fix(core): use `rglob` to guess local Python modules --- python/deptry/core.py | 2 +- tests/data/project_using_namespace/.gitignore | 1 + .../project_using_namespace/foo/api/http.py | 0 .../foo/database/bar.py | 7 ++++ .../project_using_namespace/pyproject.toml | 17 ++++++++ tests/functional/cli/test_cli_namespace.py | 39 +++++++++++++++++++ tests/functional/utils.py | 1 + 7 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/data/project_using_namespace/.gitignore create mode 100644 tests/data/project_using_namespace/foo/api/http.py create mode 100644 tests/data/project_using_namespace/foo/database/bar.py create mode 100644 tests/data/project_using_namespace/pyproject.toml create mode 100644 tests/functional/cli/test_cli_namespace.py diff --git a/python/deptry/core.py b/python/deptry/core.py index 265d4fae..d6cf64e3 100644 --- a/python/deptry/core.py +++ b/python/deptry/core.py @@ -122,7 +122,7 @@ def _is_local_module(path: Path) -> bool: """Guess if a module is a local Python module.""" return bool( (path.is_file() and path.name != "__init__.py" and path.suffix == ".py") - or (path.is_dir() and list(path.glob("*.py"))) + or (path.is_dir() and list(path.rglob("*.py"))) ) @staticmethod diff --git a/tests/data/project_using_namespace/.gitignore b/tests/data/project_using_namespace/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/tests/data/project_using_namespace/.gitignore @@ -0,0 +1 @@ +/build diff --git a/tests/data/project_using_namespace/foo/api/http.py b/tests/data/project_using_namespace/foo/api/http.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/data/project_using_namespace/foo/database/bar.py b/tests/data/project_using_namespace/foo/database/bar.py new file mode 100644 index 00000000..bbd15a79 --- /dev/null +++ b/tests/data/project_using_namespace/foo/database/bar.py @@ -0,0 +1,7 @@ +from os import chdir, walk +from pathlib import Path + +import black +import white as w + +from foo import api diff --git a/tests/data/project_using_namespace/pyproject.toml b/tests/data/project_using_namespace/pyproject.toml new file mode 100644 index 00000000..51f0a727 --- /dev/null +++ b/tests/data/project_using_namespace/pyproject.toml @@ -0,0 +1,17 @@ +[project] +# PEP 621 project metadata +# See https://www.python.org/dev/peps/pep-0621/ +name = "foo" +version = "1.2.3" +requires-python = ">=3.7" +dependencies = ["toml"] + +[project.optional-dependencies] +dev = ["black==22.10.0"] + +[build-system] +requires = ["setuptools>=61.0.0"] +build-backend = "setuptools.build_meta" + +[tool.deptry] +pep621_dev_dependency_groups = ["dev"] diff --git a/tests/functional/cli/test_cli_namespace.py b/tests/functional/cli/test_cli_namespace.py new file mode 100644 index 00000000..afb73885 --- /dev/null +++ b/tests/functional/cli/test_cli_namespace.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import uuid +from pathlib import Path +from typing import TYPE_CHECKING + +import pytest + +from tests.functional.utils import Project +from tests.utils import get_issues_report + +if TYPE_CHECKING: + from tests.utils import PipVenvFactory + + +@pytest.mark.xdist_group(name=Project.NAMESPACE) +def test_cli_with_namespace(pip_venv_factory: PipVenvFactory) -> None: + with pip_venv_factory(Project.NAMESPACE) as virtual_env: + issue_report = f"{uuid.uuid4()}.json" + result = virtual_env.run(f"deptry . -o {issue_report}") + + assert result.returncode == 1 + assert get_issues_report(Path(issue_report)) == [ + { + "error": {"code": "DEP004", "message": "'black' imported but declared as a dev dependency"}, + "module": "black", + "location": {"file": str(Path("foo/database/bar.py")), "line": 4, "column": 8}, + }, + { + "error": {"code": "DEP001", "message": "'white' imported but missing from the dependency definitions"}, + "module": "white", + "location": {"file": str(Path("foo/database/bar.py")), "line": 5, "column": 8}, + }, + { + "error": {"code": "DEP002", "message": "'toml' defined as a dependency but not used in the codebase"}, + "module": "toml", + "location": {"file": str(Path("pyproject.toml")), "line": None, "column": None}, + }, + ] diff --git a/tests/functional/utils.py b/tests/functional/utils.py index 08853829..cee3fd29 100644 --- a/tests/functional/utils.py +++ b/tests/functional/utils.py @@ -11,6 +11,7 @@ class Project(str, Enum): FUTURE_DEPRECATED_OBSOLETE_ARGUMENT = "project_with_future_deprecated_obsolete_argument" GITIGNORE = "project_with_gitignore" MULTIPLE_SOURCE_DIRECTORIES = "project_with_multiple_source_directories" + NAMESPACE = "project_using_namespace" PDM = "project_with_pdm" POETRY = "project_with_poetry" PYPROJECT_DIFFERENT_DIRECTORY = "project_with_pyproject_different_directory"