Skip to content

Commit 40c7ff8

Browse files
Don't register dependency groups until they're succesfully added (#387)
* Don't register dependency groups until they're succesfully added * Add tests for `get_default_groups`
1 parent 66d0a5a commit 40c7ff8

2 files changed

Lines changed: 78 additions & 19 deletions

File tree

src/usethis/_integrations/uv/deps.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,39 @@ def register_default_group(group: str) -> None:
6565
This ensures that dependencies in the group will be installed by default.
6666
"""
6767
if group == "dev":
68+
# Note, if the "dev" group is missing already then then we'll respect the
69+
# user's choice since they presumably would have added it themselves. So, we
70+
# won't register in that case.
6871
return
6972

70-
ensure_dev_group_is_defined()
71-
72-
try:
73-
default_groups = get_pyproject_value(["tool", "uv", "default-groups"])
74-
if not isinstance(default_groups, list):
75-
default_groups = []
76-
except KeyError:
77-
default_groups = []
73+
default_groups = get_default_groups()
7874

75+
# Choose which groups we want to add
7976
groups_to_add = []
8077
if group not in default_groups:
8178
groups_to_add.append(group)
8279
# Add "dev" if section is empty or if we're adding a new group and "dev" isn't present
8380
if (not default_groups or group != "dev") and "dev" not in default_groups:
81+
ensure_dev_group_is_defined()
8482
groups_to_add.append("dev")
8583

8684
if groups_to_add:
87-
extend_pyproject_list(["tool", "uv", "default-groups"], groups_to_add)
85+
add_default_groups(groups=groups_to_add)
86+
87+
88+
def add_default_groups(groups: list[str]) -> None:
89+
extend_pyproject_list(["tool", "uv", "default-groups"], groups)
90+
91+
92+
def get_default_groups() -> list[str]:
93+
try:
94+
default_groups = get_pyproject_value(["tool", "uv", "default-groups"])
95+
if not isinstance(default_groups, list):
96+
default_groups = []
97+
except KeyError:
98+
default_groups = []
99+
100+
return default_groups
88101

89102

90103
def ensure_dev_group_is_defined() -> None:
@@ -112,8 +125,6 @@ def add_deps_to_group(deps: list[Dependency], group: str) -> None:
112125
if usethis_config.frozen:
113126
box_print(f"Install the dependenc{ies} {deps_str}.")
114127

115-
register_default_group(group) # Register the group before adding dependencies
116-
117128
for dep in to_add_deps:
118129
try:
119130
call_uv_subprocess(
@@ -125,6 +136,9 @@ def add_deps_to_group(deps: list[Dependency], group: str) -> None:
125136
msg += (Path.cwd() / "pyproject.toml").read_text()
126137
raise UVDepGroupError(msg) from None
127138

139+
# Register the group - don't do this before adding the deps in case that step fails
140+
register_default_group(group)
141+
128142

129143
def is_dep_satisfied_in(dep: Dependency, *, in_: list[Dependency]) -> bool:
130144
return any(_is_dep_satisfied_by(dep, by=by) for by in in_)

tests/usethis/_integrations/uv/test_deps.py

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from usethis._integrations.uv.deps import (
1616
Dependency,
1717
add_deps_to_group,
18+
get_default_groups,
1819
get_dep_groups,
1920
get_deps_from_group,
2021
is_dep_in_any_group,
@@ -290,16 +291,18 @@ def mock_call_uv_subprocess(*_, **__):
290291
usethis._integrations.uv.deps, "call_uv_subprocess", mock_call_uv_subprocess
291292
)
292293

293-
with (
294-
change_cwd(uv_init_dir),
295-
PyprojectTOMLManager(),
296-
pytest.raises(
294+
# Act, Assert
295+
with change_cwd(uv_init_dir), PyprojectTOMLManager():
296+
with pytest.raises(
297297
UVDepGroupError,
298298
match="Failed to add 'pytest' to the 'test' dependency group",
299-
),
300-
):
301-
# Act
302-
add_deps_to_group([Dependency(name="pytest")], "test")
299+
):
300+
add_deps_to_group([Dependency(name="pytest")], "test")
301+
302+
# Assert contd
303+
# We want to check that registration hasn't taken place
304+
default_groups = get_default_groups()
305+
assert "test" not in default_groups
303306

304307

305308
class TestRemoveDepsFromGroup:
@@ -627,3 +630,45 @@ def test_existing_section_adds_dev_with_new_group(self, tmp_path: Path):
627630
# Assert
628631
default_groups = get_pyproject_value(["tool", "uv", "default-groups"])
629632
assert set(default_groups) == {"test", "docs", "dev"}
633+
634+
def test_dev_not_added_if_missing(self, tmp_path: Path):
635+
# Arrange
636+
(tmp_path / "pyproject.toml").write_text("""\
637+
[tool.uv]
638+
default-groups = ["test"]
639+
""")
640+
641+
with change_cwd(tmp_path), PyprojectTOMLManager():
642+
# Act
643+
register_default_group("test")
644+
645+
# Assert
646+
default_groups = get_pyproject_value(["tool", "uv", "default-groups"])
647+
assert set(default_groups) == {"test"}
648+
649+
650+
class TestGetDefaultGroups:
651+
def test_empty_pyproject_toml(self, tmp_path: Path):
652+
# Arrange
653+
(tmp_path / "pyproject.toml").touch()
654+
655+
with change_cwd(tmp_path), PyprojectTOMLManager():
656+
# Act
657+
result = get_default_groups()
658+
659+
# Assert
660+
assert result == []
661+
662+
def test_invalid_default_groups(self, tmp_path: Path):
663+
# Arrange
664+
(tmp_path / "pyproject.toml").write_text("""\
665+
[tool.uv]
666+
default-groups = "not a list"
667+
""")
668+
669+
with change_cwd(tmp_path), PyprojectTOMLManager():
670+
# Act
671+
result = get_default_groups()
672+
673+
# Assert
674+
assert result == []

0 commit comments

Comments
 (0)