Skip to content

Commit 55cd3ce

Browse files
committed
Add tests for dependency-groups parser
1 parent 4c54fc2 commit 55cd3ce

File tree

69 files changed

+361
-13
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+361
-13
lines changed

pyproject_parser/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ def load(
323323
keys = set(config.keys())
324324

325325
build_system_table: Optional[BuildSystemDict] = None
326+
dependency_groups_table: Optional[DependencyGroupsDict] = None
326327
project_table: Optional[ProjectDict] = None
327328
tool_table: Dict[str, Dict[str, Any]] = {}
328329

@@ -392,6 +393,7 @@ def dumps(
392393
"build-system": self.build_system,
393394
"project": self.project,
394395
"tool": self.tool,
396+
"dependency-groups": self.dependency_groups,
395397
}
396398

397399
if toml_dict["project"] is not None:
@@ -495,6 +497,8 @@ def from_dict(cls: Type[_PP], d: Mapping[str, Any]) -> _PP:
495497
for key, value in d.items():
496498
if key == "build-system":
497499
key = "build_system"
500+
elif key == "dependency-groups":
501+
key = "dependency_groups"
498502

499503
kwargs[key] = value
500504

@@ -511,4 +515,5 @@ def to_dict(self) -> MutableMapping[str, Any]:
511515
"build_system": self.build_system,
512516
"project": self.project,
513517
"tool": self.tool,
518+
"dependency_groups": self.dependency_groups,
514519
}

pyproject_parser/parsers.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
__all__ = [
5656
"RequiredKeysConfigParser",
5757
"BuildSystemParser",
58+
"DependencyGroupsParser",
5859
"PEP621Parser",
5960
]
6061

@@ -286,13 +287,13 @@ def parse_group(config: TOML_TYPES) -> List[Union[str, Dict[str, str]]]:
286287
if isinstance(config, list):
287288
return config
288289

289-
raise BadConfigError("A group must be a list.")
290+
raise BadConfigError("A dependency group must be an array.")
290291

291-
def parse( # type: ignore[override]
292-
self,
293-
config: Dict[str, TOML_TYPES],
294-
set_defaults: bool = False,
295-
) -> BuildSystemDict:
292+
def parse(
293+
self,
294+
config: Dict[str, TOML_TYPES],
295+
set_defaults: bool = False,
296+
) -> DependencyGroupsDict:
296297
"""
297298
Parse the TOML configuration.
298299

pyproject_parser/type_hints.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
__all__ = [
4242
"BuildSystemDict",
43+
"IncludeGroupDict",
44+
"DependencyGroupsDict",
4345
"Dynamic",
4446
"ProjectDict",
4547
"Author",
@@ -135,5 +137,10 @@ class ReadmeDict(TypedDict, total=False):
135137

136138
_PyProjectAsTomlDict = TypedDict(
137139
"_PyProjectAsTomlDict",
138-
{"build-system": Optional[BuildSystemDict], "project": Optional[ProjectDict], "tool": Dict[str, Any]},
140+
{
141+
"build-system": Optional[BuildSystemDict],
142+
"project": Optional[ProjectDict],
143+
"tool": Dict[str, Any],
144+
"dependency-groups": Optional[DependencyGroupsDict]
145+
},
139146
)

tests/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Callable, Type, TypeVar, Union
33

44
# 3rd party
5+
from dom_toml.decoder import InlineTableDict
56
from packaging.markers import Marker
67
from packaging.requirements import Requirement
78
from packaging.specifiers import SpecifierSet
@@ -46,3 +47,11 @@ def represent_readme_or_license( # noqa: MAN002
4647
data: Union[Readme, License],
4748
):
4849
return dumper.represent_dict(data.to_dict())
50+
51+
52+
@_representer_for(InlineTableDict)
53+
def represent_inline_table( # noqa: MAN002
54+
dumper: RegressionYamlDumper,
55+
data: InlineTableDict,
56+
):
57+
return dumper.represent_dict(dict(data))

tests/test_cli.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@
2727
from pyproject_parser.cli import ConfigTracebackHandler
2828
from tests.test_dumping import COMPLETE_UNDERSCORE_NAME, UNORDERED
2929

30+
COMPLETE_DEPENDENCY_GROUPS = COMPLETE_A + """
31+
32+
[dependency-groups]
33+
test = ["pytest", "coverage"]
34+
docs = ["sphinx", "sphinx-rtd-theme"]
35+
typing = ["mypy", "types-requests"]
36+
typing-test = [{include-group = "typing"}, {include-group = "test"}, "useful-types"]
37+
"""
38+
3039

3140
@pytest.mark.parametrize(
3241
"toml_string",
@@ -37,6 +46,7 @@
3746
pytest.param(COMPLETE_PROJECT_A, id="COMPLETE_PROJECT_A"),
3847
pytest.param(UNORDERED, id="UNORDERED"),
3948
pytest.param(COMPLETE_UNDERSCORE_NAME, id="COMPLETE_UNDERSCORE_NAME"),
49+
pytest.param(COMPLETE_DEPENDENCY_GROUPS, id="COMPLETE_DEPENDENCY_GROUPS"),
4050
]
4151
)
4252
@pytest.mark.parametrize("show_diff", [True, False])
@@ -177,7 +187,7 @@ def test_check_extra_deprecation_warning(
177187
),
178188
pytest.param(
179189
"[coverage]\nomit = 'demo.py'\n[flake8]\nselect = ['F401']",
180-
"Unexpected top-level key 'coverage'. Only 'build-system', 'project' and 'tool' are allowed.",
190+
"Unexpected top-level key 'coverage'. Only 'build-system', 'dependency-groups', 'project' and 'tool' are allowed.",
181191
id="top-level",
182192
),
183193
pytest.param(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
BadConfigError: Unexpected top-level key 'coverage'. Only 'build-system', 'project' and 'tool' are allowed.
1+
BadConfigError: Unexpected top-level key 'coverage'. Only 'build-system', 'dependency-groups', 'project' and 'tool' are allowed.
22
Use '--traceback' to view the full traceback.
33
Aborted!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reformatting 'pyproject.toml'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[build-system]
2+
requires = [ "whey",]
3+
build-backend = "whey"
4+
5+
[project]
6+
name = "whey"
7+
version = "2021.0.0"
8+
description = "A simple Python wheel builder for simple projects."
9+
keywords = [ "build", "distribution", "packaging", "pep517", "pep621", "sdist", "wheel",]
10+
dependencies = [ 'django>2.1; os_name != "nt"', 'django>2.0; os_name == "nt"', "gidgethub[httpx]>4.0.0", "httpx",]
11+
dynamic = [ "classifiers", "requires-python",]
12+
13+
[[project.authors]]
14+
name = "Dominic Davis-Foster"
15+
16+
17+
[project.urls]
18+
Homepage = "https://whey.readthedocs.io/en/latest"
19+
Documentation = "https://whey.readthedocs.io/en/latest"
20+
"Issue Tracker" = "https://github.com/repo-helper/whey/issues"
21+
"Source Code" = "https://github.com/repo-helper/whey"
22+
23+
[tool.whey]
24+
base-classifiers = [ "Development Status :: 4 - Beta",]
25+
python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10",]
26+
python-implementations = [ "CPython", "PyPy",]
27+
platforms = [ "Windows", "macOS", "Linux",]
28+
license-key = "MIT"
29+
30+
[dependency-groups]
31+
test = [ "pytest", "coverage",]
32+
docs = [ "sphinx", "sphinx-rtd-theme",]
33+
typing = [ "mypy", "types-requests",]
34+
typing-test = [ { include-group = "typing" }, { include-group = "test" }, "useful-types",]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Reformatting 'pyproject.toml'
2+
--- pyproject.toml (original)
3+
+++ pyproject.toml (reformatted)
4+
@@ -6,18 +6,13 @@
5+
name = "whey"
6+
version = "2021.0.0"
7+
description = "A simple Python wheel builder for simple projects."
8+
-keywords = [ "pep517", "pep621", "build", "sdist", "wheel", "packaging", "distribution",]
9+
+keywords = [ "build", "distribution", "packaging", "pep517", "pep621", "sdist", "wheel",]
10+
+dependencies = [ 'django>2.1; os_name != "nt"', 'django>2.0; os_name == "nt"', "gidgethub[httpx]>4.0.0", "httpx",]
11+
dynamic = [ "classifiers", "requires-python",]
12+
-dependencies = [
13+
- "httpx",
14+
- "gidgethub[httpx]>4.0.0",
15+
- "django>2.1; os_name != 'nt'",
16+
- "django>2.0; os_name == 'nt'"
17+
-]
18+
19+
[[project.authors]]
20+
+name = "Dominic Davis-Foster"
21+
22+
-name = "Dominic Davis-Foster"
23+
24+
[project.urls]
25+
Homepage = "https://whey.readthedocs.io/en/latest"
26+
@@ -32,10 +27,9 @@
27+
platforms = [ "Windows", "macOS", "Linux",]
28+
license-key = "MIT"
29+
30+
+[dependency-groups]
31+
+test = [ "pytest", "coverage",]
32+
+docs = [ "sphinx", "sphinx-rtd-theme",]
33+
+typing = [ "mypy", "types-requests",]
34+
+typing-test = [ { include-group = "typing" }, { include-group = "test" }, "useful-types",]
35+
36+
-[dependency-groups]
37+
-test = ["pytest", "coverage"]
38+
-docs = ["sphinx", "sphinx-rtd-theme"]
39+
-typing = ["mypy", "types-requests"]
40+
-typing-test = [{include-group = "typing"}, {include-group = "test"}, "useful-types"]
41+
-
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[build-system]
2+
requires = [ "whey",]
3+
build-backend = "whey"
4+
5+
[project]
6+
name = "whey"
7+
version = "2021.0.0"
8+
description = "A simple Python wheel builder for simple projects."
9+
keywords = [ "build", "distribution", "packaging", "pep517", "pep621", "sdist", "wheel",]
10+
dependencies = [ 'django>2.1; os_name != "nt"', 'django>2.0; os_name == "nt"', "gidgethub[httpx]>4.0.0", "httpx",]
11+
dynamic = [ "classifiers", "requires-python",]
12+
13+
[[project.authors]]
14+
name = "Dominic Davis-Foster"
15+
16+
17+
[project.urls]
18+
Homepage = "https://whey.readthedocs.io/en/latest"
19+
Documentation = "https://whey.readthedocs.io/en/latest"
20+
"Issue Tracker" = "https://github.com/repo-helper/whey/issues"
21+
"Source Code" = "https://github.com/repo-helper/whey"
22+
23+
[tool.whey]
24+
base-classifiers = [ "Development Status :: 4 - Beta",]
25+
python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10",]
26+
python-implementations = [ "CPython", "PyPy",]
27+
platforms = [ "Windows", "macOS", "Linux",]
28+
license-key = "MIT"
29+
30+
[dependency-groups]
31+
test = [ "pytest", "coverage",]
32+
docs = [ "sphinx", "sphinx-rtd-theme",]
33+
typing = [ "mypy", "types-requests",]
34+
typing-test = [ { include-group = "typing" }, { include-group = "test" }, "useful-types",]

tests/test_config.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
from shippinglabel import normalize_keep_dot
1919

2020
# this package
21-
from pyproject_parser.parsers import BuildSystemParser, PEP621Parser, RequiredKeysConfigParser
21+
from pyproject_parser.parsers import (
22+
BuildSystemParser,
23+
DependencyGroupsParser,
24+
PEP621Parser,
25+
RequiredKeysConfigParser
26+
)
2227
from pyproject_parser.utils import PyProjectDeprecationWarning, _load_toml
2328

2429

@@ -555,3 +560,46 @@ class MyConfigParser(RequiredKeysConfigParser):
555560

556561
assert MyConfigParser().parse({}, set_defaults=True) == {"foo": "foo-default", "bar": "bar-defaults"}
557562
assert MyConfigParser().parse({"foo": "baz"}, set_defaults=True) == {"foo": "baz", "bar": "bar-defaults"}
563+
564+
565+
valid_dependency_groups_config = [
566+
pytest.param("[dependency-groups]", id="empty"),
567+
pytest.param('[dependency-groups]\ngroup-a = ["foo"]', id="one-group"),
568+
pytest.param(
569+
'[dependency-groups]\ngroup-a = ["foo"]\ngroup-b = ["foo>1.0"]\ngroup-c = ["foo<1.0"]\nall = ["foo", {include-group = "group-a"}, {include-group = "group-b"}, {include-group = "group-c"}]',
570+
id="full-example"
571+
),
572+
]
573+
574+
bad_dependency_groups_config = [
575+
pytest.param(
576+
'[dependency-groups]\ngroup-a = "foo"', BadConfigError, "A dependency group must be an array"
577+
),
578+
]
579+
580+
581+
@pytest.mark.parametrize("set_defaults", [True, False])
582+
@pytest.mark.parametrize("toml_config", valid_dependency_groups_config)
583+
def test_dependency_groups_parser_valid_config(
584+
toml_config: str,
585+
tmp_pathplus: PathPlus,
586+
advanced_data_regression: AdvancedDataRegressionFixture,
587+
set_defaults: bool,
588+
):
589+
(tmp_pathplus / "pyproject.toml").write_clean(toml_config)
590+
config = DependencyGroupsParser().parse(
591+
_load_toml(tmp_pathplus / "pyproject.toml")["dependency-groups"],
592+
set_defaults=set_defaults,
593+
)
594+
595+
advanced_data_regression.check(config)
596+
597+
598+
@pytest.mark.parametrize("config, expects, match", bad_dependency_groups_config)
599+
def test_dependency_groups_parser_errors(
600+
config: str, expects: Type[Exception], match: str, tmp_pathplus: PathPlus
601+
):
602+
(tmp_pathplus / "pyproject.toml").write_clean(config)
603+
604+
with in_directory(tmp_pathplus), pytest.raises(expects, match=match):
605+
DependencyGroupsParser().parse(_load_toml(tmp_pathplus / "pyproject.toml")["dependency-groups"])
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
all:
2+
- foo
3+
- include-group: group-a
4+
- include-group: group-b
5+
- include-group: group-c
6+
group-a:
7+
- foo
8+
group-b:
9+
- foo>1.0
10+
group-c:
11+
- foo<1.0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
all:
2+
- foo
3+
- include-group: group-a
4+
- include-group: group-b
5+
- include-group: group-c
6+
group-a:
7+
- foo
8+
group-b:
9+
- foo>1.0
10+
group-c:
11+
- foo<1.0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
group-a:
2+
- foo
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
group-a:
2+
- foo

tests/test_pyproject_class.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,24 @@
1717
# this package
1818
from pyproject_parser import PyProject
1919

20+
COMPLETE_DEPENDENCY_GROUPS = COMPLETE_A + """
2021
21-
@pytest.mark.parametrize("toml_config", [*valid_pep621_config, *valid_buildsystem_config])
22+
[dependency-groups]
23+
test = ["pytest", "coverage"]
24+
docs = ["sphinx", "sphinx-rtd-theme"]
25+
typing = ["mypy", "types-requests"]
26+
typing-test = [{include-group = "typing"}, {include-group = "test"}, "useful-types"]
27+
"""
28+
29+
30+
@pytest.mark.parametrize(
31+
"toml_config",
32+
[
33+
*valid_pep621_config,
34+
*valid_buildsystem_config,
35+
pytest.param(COMPLETE_DEPENDENCY_GROUPS, id="complete-dependency-groups"),
36+
]
37+
)
2238
def test_valid_config(
2339
toml_config: str,
2440
tmp_pathplus: PathPlus,
@@ -81,13 +97,13 @@ def test_valid_config_resolve_files(
8197
pytest.param(
8298
'banana = "fruit"\n[project]\nname = "food"',
8399
BadConfigError,
84-
"Unexpected top-level key 'banana'. Only 'build-system', 'project' and 'tool' are allowed.",
100+
"Unexpected top-level key 'banana'. Only 'build-system', 'dependency-groups', 'project' and 'tool' are allowed.",
85101
id="unexpected_top_level"
86102
),
87103
pytest.param(
88104
"[coverage]\nomit = 'demo.py'\n[flake8]\nselect = ['F401']",
89105
BadConfigError,
90-
"Unexpected top-level key 'coverage'. Only 'build-system', 'project' and 'tool' are allowed.",
106+
"Unexpected top-level key 'coverage'. Only 'build-system', 'dependency-groups', 'project' and 'tool' are allowed.",
91107
id="top-level",
92108
),
93109
pytest.param(

tests/test_pyproject_class_/test_custom_pyproject_class_COMPLETE_A_.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ build_system:
22
build-backend: whey
33
requires:
44
- whey
5+
dependency_groups: null
56
project:
67
authors:
78

0 commit comments

Comments
 (0)