diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f4d45f5..349dcc77 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,6 +37,7 @@ repos: files: ^nox/ args: [] additional_dependencies: + - dependency-groups>=1.2 - jinja2 - packaging - importlib_metadata diff --git a/nox/project.py b/nox/project.py index 24a4712e..61c63152 100644 --- a/nox/project.py +++ b/nox/project.py @@ -6,7 +6,9 @@ from pathlib import Path from typing import TYPE_CHECKING +import packaging.requirements import packaging.specifiers +from dependency_groups import resolve if TYPE_CHECKING: from typing import Any @@ -17,7 +19,7 @@ import tomllib -__all__ = ["load_toml", "python_versions"] +__all__ = ["load_toml", "python_versions", "dependency_groups"] def __dir__() -> list[str]: @@ -127,3 +129,20 @@ def python_versions( max_minor_version = int(max_version.split(".")[1]) return [f"3.{v}" for v in range(min_minor_version, max_minor_version + 1)] + + +def dependency_groups(pyproject: dict[str, Any], *groups: str) -> tuple[str, ...]: + """ + Get a list of dependencies from a ``[dependency-groups]`` section(s). + + Example: + + .. code-block:: python + + @nox.session + def test(session): + pyproject = nox.project.load_toml("pyproject.toml") + session.install(*nox.project.dependency_groups(pyproject, "dev")) + """ + dep_groups = pyproject["dependency-groups"] + return resolve(dep_groups, *groups) diff --git a/pyproject.toml b/pyproject.toml index c0d100bf..a179c049 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ classifiers = [ dependencies = [ "argcomplete<4,>=1.9.4", "colorlog<7,>=2.6.1", + "dependency-groups>=1.1", "packaging>=20.9", "tomli>=1; python_version<'3.11'", "virtualenv>=20.14.1", diff --git a/tests/test_project.py b/tests/test_project.py index a522c77c..3854902a 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -1,6 +1,6 @@ import pytest -from nox.project import python_versions +from nox.project import dependency_groups, python_versions def test_classifiers(): @@ -63,3 +63,34 @@ def test_python_range_no_min(): with pytest.raises(ValueError, match="No minimum version found"): python_versions(pyproject, max_version="3.5") + + +def test_dependency_groups(): + example = { + "dependency-groups": { + "test": ["pytest", "coverage"], + "docs": ["sphinx", "sphinx-rtd-theme"], + "typing": ["mypy", "types-requests"], + "typing-test": [ + {"include-group": "typing"}, + {"include-group": "test"}, + "useful-types", + ], + } + } + + assert dependency_groups(example, "test") == ("pytest", "coverage") + assert dependency_groups(example, "typing-test") == ( + "mypy", + "types-requests", + "pytest", + "coverage", + "useful-types", + ) + assert dependency_groups(example, "typing_test") == ( + "mypy", + "types-requests", + "pytest", + "coverage", + "useful-types", + )