Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(poetry): consider all groups for dev dependencies #392

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions deptry/dependency_getter/poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ def _get_poetry_dev_dependencies(self) -> list[Dependency]:
pyproject_data = load_pyproject_toml(self.config)

with contextlib.suppress(KeyError):
dependencies = {**pyproject_data["tool"]["poetry"]["dev-dependencies"], **dependencies}
dependencies = {**dependencies, **pyproject_data["tool"]["poetry"]["dev-dependencies"]}

with contextlib.suppress(KeyError):
dependencies = {**pyproject_data["tool"]["poetry"]["group"]["dev"]["dependencies"], **dependencies}
try:
dependency_groups = pyproject_data["tool"]["poetry"]["group"]
except KeyError:
dependency_groups = {}

for group_values in dependency_groups.values():
with contextlib.suppress(KeyError):
dependencies = {**dependencies, **group_values["dependencies"]}

return self._get_dependencies(dependencies, self.package_module_name_map)

Expand Down
2 changes: 2 additions & 0 deletions tests/data/project_with_poetry/poetry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[virtualenvs]
in-project = true
33 changes: 33 additions & 0 deletions tests/data/project_with_poetry/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[tool.poetry]
name = "test"
version = "0.0.1"
description = "A test project"
authors = ["test <test@test.com>"]

[tool.poetry.dependencies]
python = ">=3.7"
pkginfo = ">=1.8.3"
toml = "*"
urllib3 = ">=1.26.12"

click = { version = ">=8.1.3", optional = true }
isort = { version = ">=5.10.1", optional = true }
requests = { version = ">=2.28.1", optional = true }

[tool.poetry.extras]
foo = [
"click",
"isort",
]
bar = ["requests"]

[tool.poetry.group.lint.dependencies]
black = "^22.6.0"
mypy = "^1.3.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.3.0"
pytest-cov = "^4.0.0"

[tool.deptry]
ignore_unused = ["pkginfo"]
10 changes: 10 additions & 0 deletions tests/data/project_with_poetry/src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from os import chdir, walk
from pathlib import Path

import black
import click
import mypy
import pytest
import pytest_cov
import white as w
from urllib3 import contrib
37 changes: 37 additions & 0 deletions tests/data/project_with_poetry/src/notebook.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "9f4924ec-2200-4801-9d49-d4833651cbc4",
"metadata": {},
"outputs": [],
"source": [
"import click\n",
"from urllib3 import contrib\n",
"import toml"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
105 changes: 105 additions & 0 deletions tests/functional/cli/test_cli_poetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from click.testing import CliRunner

from deptry.cli import deptry
from tests.utils import get_issues_report, run_within_dir

if TYPE_CHECKING:
from tests.functional.types import ToolSpecificProjectBuilder


def test_cli_with_poetry(poetry_project_builder: ToolSpecificProjectBuilder) -> None:
with run_within_dir(poetry_project_builder("project_with_poetry")):
result = CliRunner().invoke(deptry, ". -o report.json")

assert result.exit_code == 1
assert get_issues_report() == [
{
"error": {
"code": "DEP002",
"message": "'isort' defined as a dependency but not used in the codebase",
},
"module": "isort",
"location": {
"file": str(Path("pyproject.toml")),
"line": None,
"column": None,
},
},
{
"error": {
"code": "DEP002",
"message": "'requests' defined as a dependency but not used in the codebase",
},
"module": "requests",
"location": {
"file": str(Path("pyproject.toml")),
"line": None,
"column": None,
},
},
{
"error": {
"code": "DEP004",
"message": "'black' imported but declared as a dev dependency",
},
"module": "black",
"location": {
"file": str(Path("src/main.py")),
"line": 4,
"column": 0,
},
},
{
"error": {
"code": "DEP004",
"message": "'mypy' imported but declared as a dev dependency",
},
"module": "mypy",
"location": {
"file": str(Path("src/main.py")),
"line": 6,
"column": 0,
},
},
{
"error": {
"code": "DEP004",
"message": "'pytest' imported but declared as a dev dependency",
},
"module": "pytest",
"location": {
"file": str(Path("src/main.py")),
"line": 7,
"column": 0,
},
},
{
"error": {
"code": "DEP004",
"message": "'pytest_cov' imported but declared as a dev dependency",
},
"module": "pytest_cov",
"location": {
"file": str(Path("src/main.py")),
"line": 8,
"column": 0,
},
},
{
"error": {
"code": "DEP001",
"message": "'white' imported but missing from the dependency definitions",
},
"module": "white",
"location": {
"file": str(Path("src/main.py")),
"line": 9,
"column": 0,
},
},
]
36 changes: 33 additions & 3 deletions tests/unit/dependency_getter/test_poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@


def test_dependency_getter(tmp_path: Path) -> None:
fake_pyproject_toml = """[tool.poetry.dependencies]
fake_pyproject_toml = """
[tool.poetry.dependencies]
python = ">=3.7,<4.0"
bar = { version = ">=2.5.1,<4.0.0", python = ">3.7" }
foo-bar = { version = ">=2.5.1,<4.0.0", optional = true, python = ">3.7" }
fox-python = "*" # top level module is called "fox"

[tool.poetry.dev-dependencies]
toml = "^0.10.2"
qux = { version = ">=2.5.1,<4.0.0", optional = true }"""
qux = { version = ">=2.5.1,<4.0.0", optional = true }

[tool.poetry.group.lint.dependencies]
black = "^22.6.0"
mypy = "^1.3.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.3.0"
pytest-cov = "^4.0.0"
"""

with run_within_dir(tmp_path):
with Path("pyproject.toml").open("w") as f:
Expand All @@ -30,7 +40,7 @@ def test_dependency_getter(tmp_path: Path) -> None:
dev_dependencies = dependencies_extract.dev_dependencies

assert len(dependencies) == 3
assert len(dev_dependencies) == 2
assert len(dev_dependencies) == 6

assert dependencies[0].name == "bar"
assert dependencies[0].is_conditional
Expand All @@ -56,3 +66,23 @@ def test_dependency_getter(tmp_path: Path) -> None:
assert not dev_dependencies[1].is_conditional
assert dev_dependencies[1].is_optional
assert "qux" in dev_dependencies[1].top_levels

assert dev_dependencies[2].name == "black"
assert not dev_dependencies[2].is_conditional
assert not dev_dependencies[2].is_optional
assert "black" in dev_dependencies[2].top_levels

assert dev_dependencies[3].name == "mypy"
assert not dev_dependencies[3].is_conditional
assert not dev_dependencies[3].is_optional
assert "mypy" in dev_dependencies[3].top_levels

assert dev_dependencies[4].name == "pytest"
assert not dev_dependencies[4].is_conditional
assert not dev_dependencies[4].is_optional
assert "pytest" in dev_dependencies[4].top_levels

assert dev_dependencies[5].name == "pytest-cov"
assert not dev_dependencies[5].is_conditional
assert not dev_dependencies[5].is_optional
assert "pytest_cov" in dev_dependencies[5].top_levels