Skip to content

Commit

Permalink
feat(poetry): extend PEP 621 dependency getter
Browse files Browse the repository at this point in the history
  • Loading branch information
mkniewallner committed Jan 9, 2025
1 parent e157c84 commit 343e755
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 64 deletions.
6 changes: 4 additions & 2 deletions python/deptry/dependency_getter/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

from deptry.dependency_getter.pep621.base import PEP621DependencyGetter
from deptry.dependency_getter.pep621.pdm import PDMDependencyGetter
from deptry.dependency_getter.pep621.poetry import PoetryDependencyGetter
from deptry.dependency_getter.pep621.uv import UvDependencyGetter
from deptry.dependency_getter.poetry import PoetryDependencyGetter
from deptry.dependency_getter.requirements_files import RequirementsTxtDependencyGetter
from deptry.exceptions import DependencySpecificationNotFoundError
from deptry.utils import load_pyproject_toml
Expand Down Expand Up @@ -45,7 +45,9 @@ def build(self) -> DependencyGetter:
pyproject_toml = load_pyproject_toml(self.config)

if self._project_uses_poetry(pyproject_toml):
return PoetryDependencyGetter(self.config, self.package_module_name_map)
return PoetryDependencyGetter(
self.config, self.package_module_name_map, self.pep621_dev_dependency_groups
)

if self._project_uses_uv(pyproject_toml):
return UvDependencyGetter(self.config, self.package_module_name_map, self.pep621_dev_dependency_groups)
Expand Down
76 changes: 76 additions & 0 deletions python/deptry/dependency_getter/pep621/poetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from __future__ import annotations

import contextlib
from dataclasses import dataclass
from typing import Any

from deptry.dependency import Dependency
from deptry.dependency_getter.pep621.base import PEP621DependencyGetter
from deptry.utils import load_pyproject_toml


@dataclass
class PoetryDependencyGetter(PEP621DependencyGetter):
"""
Class that retrieves dependencies from a project that uses Poetry, either through PEP 621 syntax, Poetry specific
syntax, or a mix of both.
"""

def _get_dependencies(self) -> list[Dependency]:
"""
Retrieve dependencies from either:
- `[project.dependencies]` defined by PEP 621
- `[tool.poetry.dependencies]` which is specific to Poetry
If dependencies are set in `[project.dependencies]`, then assume that the project uses PEP 621 format to define
dependencies. Even if `[tool.poetry.dependencies]` is populated, having entries in `[project.dependencies]`
means that `[tool.poetry.dependencies]` is only used to enrich existing dependencies, and cannot be used to
define additional ones.
If no dependencies are found in `[project.dependencies]`, then extract dependencies present in
`[tool.poetry.dependencies]`.
"""
if dependencies := super()._get_dependencies():
return dependencies

pyproject_data = load_pyproject_toml(self.config)
return self._extract_poetry_dependencies(pyproject_data["tool"]["poetry"].get("dependencies", {}))

def _get_dev_dependencies(
self,
dependency_groups_dependencies: dict[str, list[Dependency]],
dev_dependencies_from_optional: list[Dependency],
) -> list[Dependency]:
"""
Poetry's development dependencies can be specified under either, or both:
- [tool.poetry.dev-dependencies]
- [tool.poetry.group.<group>.dependencies]
"""
dev_dependencies = super()._get_dev_dependencies(dependency_groups_dependencies, dev_dependencies_from_optional)

pyproject_data = load_pyproject_toml(self.config)
poetry_dev_dependencies: dict[str, str] = {}

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

try:
dependency_groups = pyproject_data["tool"]["poetry"]["group"]
except KeyError:
dependency_groups = {}

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

return [*dev_dependencies, *self._extract_poetry_dependencies(poetry_dev_dependencies)]

def _extract_poetry_dependencies(self, poetry_dependencies: dict[str, Any]) -> list[Dependency]:
return [
Dependency(dep, self.config, module_names=self.package_module_name_map.get(dep))
for dep in poetry_dependencies
if dep != "python"
]
60 changes: 0 additions & 60 deletions python/deptry/dependency_getter/poetry.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/unit/dependency_getter/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from deptry.dependency_getter.builder import DependencyGetterBuilder
from deptry.dependency_getter.pep621.base import PEP621DependencyGetter
from deptry.dependency_getter.pep621.pdm import PDMDependencyGetter
from deptry.dependency_getter.pep621.poetry import PoetryDependencyGetter
from deptry.dependency_getter.pep621.uv import UvDependencyGetter
from deptry.dependency_getter.poetry import PoetryDependencyGetter
from deptry.dependency_getter.requirements_files import RequirementsTxtDependencyGetter
from deptry.exceptions import DependencySpecificationNotFoundError
from tests.utils import run_within_dir
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/dependency_getter/test_poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from pathlib import Path

from deptry.dependency_getter.poetry import PoetryDependencyGetter
from deptry.dependency_getter.pep621.poetry import PoetryDependencyGetter
from tests.utils import run_within_dir


Expand Down

0 comments on commit 343e755

Please sign in to comment.