Skip to content

Commit 6dd166a

Browse files
Add tests for TestAddPyprojectConfigs (#225)
1 parent c9d753c commit 6dd166a

4 files changed

Lines changed: 111 additions & 13 deletions

File tree

src/usethis/_integrations/pyproject/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55

66
class PyProjectConfig(BaseModel):
77
id_keys: list[str]
8-
main_contents: dict[str, Any]
8+
value: Any

src/usethis/_integrations/pyproject/core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ def set_config_value(
4545
pyproject = read_pyproject_toml()
4646

4747
try:
48+
# Index our way into each ID key.
49+
# Eventually, we should land at a final dict, which si the one we are setting.
4850
p, parent = pyproject, {}
4951
for key in id_keys:
5052
TypeAdapter(dict).validate_python(p)

src/usethis/_tool.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def add_pyproject_configs(self) -> None:
135135
first_addition = True
136136
for config in configs:
137137
try:
138-
set_config_value(config.id_keys, config.main_contents)
138+
set_config_value(config.id_keys, config.value)
139139
except PyProjectTOMLValueAlreadySetError:
140140
pass
141141
else:
@@ -223,7 +223,7 @@ def get_pyproject_configs(self) -> list[PyProjectConfig]:
223223
return [
224224
PyProjectConfig(
225225
id_keys=["tool", "pyproject-fmt"],
226-
main_contents={"keep_full_version": True},
226+
value={"keep_full_version": True},
227227
)
228228
]
229229

@@ -244,7 +244,7 @@ def get_pyproject_configs(self) -> list[PyProjectConfig]:
244244
return [
245245
PyProjectConfig(
246246
id_keys=["tool", "pytest"],
247-
main_contents={
247+
value={
248248
"ini_options": {
249249
"testpaths": ["tests"],
250250
"addopts": [
@@ -256,14 +256,14 @@ def get_pyproject_configs(self) -> list[PyProjectConfig]:
256256
),
257257
PyProjectConfig(
258258
id_keys=["tool", "coverage", "run"],
259-
main_contents={
259+
value={
260260
"source": ["src"],
261261
"omit": ["*/pytest-of-*/*"],
262262
},
263263
),
264264
PyProjectConfig(
265265
id_keys=["tool", "coverage", "report"],
266-
main_contents={
266+
value={
267267
"exclude_also": [
268268
"if TYPE_CHECKING:",
269269
"raise AssertionError",
@@ -369,7 +369,7 @@ def get_pyproject_configs(self) -> list[PyProjectConfig]:
369369
return [
370370
PyProjectConfig(
371371
id_keys=["tool", "ruff"],
372-
main_contents={
372+
value={
373373
"src": ["src"],
374374
"line-length": 88,
375375
"lint": {"select": []},

tests/usethis/test_tool.py

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ def get_pre_commit_repos(self) -> list[LocalRepo | UriRepo]:
4545
]
4646

4747
def get_pyproject_configs(self) -> list[PyProjectConfig]:
48-
return [
49-
PyProjectConfig(id_keys=["tool", self.name], main_contents={"key": "value"})
50-
]
48+
return [PyProjectConfig(id_keys=["tool", self.name], value={"key": "value"})]
5149

5250
def get_associated_ruff_rules(self) -> list[str]:
5351
return ["MYRULE"]
@@ -117,9 +115,7 @@ def test_default(self):
117115
def test_specific(self):
118116
tool = MyTool()
119117
assert tool.get_pyproject_configs() == [
120-
PyProjectConfig(
121-
id_keys=["tool", "my_tool"], main_contents={"key": "value"}
122-
)
118+
PyProjectConfig(id_keys=["tool", "my_tool"], value={"key": "value"})
123119
]
124120

125121
class TestGetAssociatedRuffRules:
@@ -545,3 +541,103 @@ def get_pre_commit_repos(self) -> list[LocalRepo | UriRepo]:
545541
# Assert
546542
assert (tmp_path / ".pre-commit-config.yaml").exists()
547543
assert get_hook_names() == [_PLACEHOLDER_ID]
544+
545+
class TestAddPyprojectConfigs:
546+
def test_no_config(self, tmp_path: Path):
547+
# Arrange
548+
class NoConfigTool(Tool):
549+
@property
550+
def name(self) -> str:
551+
return "no_config_tool"
552+
553+
def get_pyproject_configs(self) -> list[PyProjectConfig]:
554+
return []
555+
556+
nc_tool = NoConfigTool()
557+
558+
# Act
559+
with change_cwd(tmp_path):
560+
nc_tool.add_pyproject_configs()
561+
562+
# Assert
563+
assert not (tmp_path / "pyproject.toml").exists()
564+
565+
def test_empty(self, tmp_path: Path, capfd: pytest.CaptureFixture[str]):
566+
# Arrange
567+
class ThisTool(Tool):
568+
@property
569+
def name(self) -> str:
570+
return "mytool"
571+
572+
def get_pyproject_configs(self) -> list[PyProjectConfig]:
573+
return [
574+
PyProjectConfig(
575+
id_keys=["tool", "mytool"],
576+
value={"key": "value"},
577+
),
578+
]
579+
580+
(tmp_path / "pyproject.toml").write_text("")
581+
582+
# Act
583+
with change_cwd(tmp_path):
584+
ThisTool().add_pyproject_configs()
585+
586+
# Assert
587+
assert (
588+
(tmp_path / "pyproject.toml").read_text()
589+
== """\
590+
[tool.mytool]
591+
key = "value"
592+
"""
593+
)
594+
out, err = capfd.readouterr()
595+
assert not err
596+
assert out == "✔ Adding mytool config to 'pyproject.toml'.\n"
597+
598+
def test_differing_sections(
599+
self, tmp_path: Path, capfd: pytest.CaptureFixture[str]
600+
):
601+
# https://github.com/nathanjmcdougall/usethis-python/issues/184
602+
603+
# Arrange
604+
class ThisTool(Tool):
605+
@property
606+
def name(self) -> str:
607+
return "mytool"
608+
609+
def get_pyproject_configs(self) -> list[PyProjectConfig]:
610+
return [
611+
PyProjectConfig(
612+
id_keys=["tool", "mytool", "name"],
613+
value="Modular Design",
614+
),
615+
PyProjectConfig(
616+
id_keys=["tool", "mytool", "root_packages"],
617+
value=["example"],
618+
),
619+
]
620+
621+
(tmp_path / "pyproject.toml").write_text(
622+
"""\
623+
[tool.mytool]
624+
name = "Modular Design"
625+
"""
626+
)
627+
628+
# Act
629+
with change_cwd(tmp_path):
630+
ThisTool().add_pyproject_configs()
631+
632+
# Assert
633+
assert (
634+
(tmp_path / "pyproject.toml").read_text()
635+
== """\
636+
[tool.mytool]
637+
name = "Modular Design"
638+
root_packages = ["example"]
639+
"""
640+
)
641+
out, err = capfd.readouterr()
642+
assert not err
643+
assert out == "✔ Adding mytool config to 'pyproject.toml'.\n"

0 commit comments

Comments
 (0)