copier-python 0.19.0__tar.gz → 0.19.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {copier_python-0.19.0 → copier_python-0.19.1}/CONTRIBUTING.md +8 -0
  2. {copier_python-0.19.0 → copier_python-0.19.1}/PKG-INFO +1 -1
  3. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_workflows.ambr +1 -70
  4. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_contributing.py +2 -2
  5. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_docs.py +2 -2
  6. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_license.py +3 -24
  7. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_pyproject.py +2 -2
  8. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_readme.py +2 -2
  9. copier_python-0.19.1/tests/template/test_structure.py +156 -0
  10. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_workflows.py +1 -7
  11. {copier_python-0.19.0 → copier_python-0.19.1}/tests/utils.py +9 -7
  12. copier_python-0.19.0/tests/template/test_structure.py +0 -107
  13. {copier_python-0.19.0 → copier_python-0.19.1}/.gitignore +0 -0
  14. {copier_python-0.19.0 → copier_python-0.19.1}/AGENTS.md +0 -0
  15. {copier_python-0.19.0 → copier_python-0.19.1}/LICENSE +0 -0
  16. {copier_python-0.19.0 → copier_python-0.19.1}/README.md +0 -0
  17. {copier_python-0.19.0 → copier_python-0.19.1}/copier_python/__init__.py +0 -0
  18. {copier_python-0.19.0 → copier_python-0.19.1}/copier_python/__main__.py +0 -0
  19. {copier_python-0.19.0 → copier_python-0.19.1}/copier_python/py.typed +0 -0
  20. {copier_python-0.19.0 → copier_python-0.19.1}/copier_python/repo.py +0 -0
  21. {copier_python-0.19.0 → copier_python-0.19.1}/copier_python/update.py +0 -0
  22. {copier_python-0.19.0 → copier_python-0.19.1}/docs/contributing.md +0 -0
  23. {copier_python-0.19.0 → copier_python-0.19.1}/docs/development/requirements.md +0 -0
  24. {copier_python-0.19.0 → copier_python-0.19.1}/docs/development/updates.md +0 -0
  25. {copier_python-0.19.0 → copier_python-0.19.1}/docs/development/workflow.md +0 -0
  26. {copier_python-0.19.0 → copier_python-0.19.1}/docs/index.md +0 -0
  27. {copier_python-0.19.0 → copier_python-0.19.1}/docs/license.md +0 -0
  28. {copier_python-0.19.0 → copier_python-0.19.1}/docs/project-creation.md +0 -0
  29. {copier_python-0.19.0 → copier_python-0.19.1}/docs/project-development.md +0 -0
  30. {copier_python-0.19.0 → copier_python-0.19.1}/docs/project-release.md +0 -0
  31. {copier_python-0.19.0 → copier_python-0.19.1}/docs/project-setup.md +0 -0
  32. {copier_python-0.19.0 → copier_python-0.19.1}/docs/project-updates.md +0 -0
  33. {copier_python-0.19.0 → copier_python-0.19.1}/docs/releasing.md +0 -0
  34. {copier_python-0.19.0 → copier_python-0.19.1}/docs/requirements.md +0 -0
  35. {copier_python-0.19.0 → copier_python-0.19.1}/docs/setup.md +0 -0
  36. {copier_python-0.19.0 → copier_python-0.19.1}/pyproject.toml +0 -0
  37. {copier_python-0.19.0 → copier_python-0.19.1}/tests/__init__.py +0 -0
  38. {copier_python-0.19.0 → copier_python-0.19.1}/tests/conftest.py +0 -0
  39. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__init__.py +0 -0
  40. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_agents.ambr +0 -0
  41. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_compose.ambr +0 -0
  42. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_contributing.ambr +0 -0
  43. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_dockerfile.ambr +0 -0
  44. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_docs.ambr +0 -0
  45. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_license.ambr +0 -0
  46. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_mise_toml.ambr +0 -0
  47. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_pyproject.ambr +0 -0
  48. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_readme.ambr +0 -0
  49. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/__snapshots__/test_zensical.ambr +0 -0
  50. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_agents.py +0 -0
  51. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_compose.py +0 -0
  52. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_dockerfile.py +0 -0
  53. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_mise_toml.py +0 -0
  54. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_template.py +0 -0
  55. {copier_python-0.19.0 → copier_python-0.19.1}/tests/template/test_zensical.py +0 -0
  56. {copier_python-0.19.0 → copier_python-0.19.1}/tests/test_update.py +0 -0
  57. {copier_python-0.19.0 → copier_python-0.19.1}/tests/test_version.py +0 -0
@@ -13,3 +13,11 @@ Thank you for your time and interest in improving
13
13
  for submitting pull requests
14
14
  * **Issue tracker**: <https://github.com/smkent/copier-python/issues>
15
15
  for questions or bug reports
16
+
17
+ ## Contribution terms
18
+
19
+ By submitting a contribution to copier-python, you agree that it is
20
+ licensed under the project's license, the
21
+ [MIT License](https://github.com/smkent/copier-python/blob/main/LICENSE),
22
+ with no additional terms,
23
+ and that you have the right to submit it under that license.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: copier-python
3
- Version: 0.19.0
3
+ Version: 0.19.1
4
4
  Summary: Copier template for Python projects with modern tooling
5
5
  Project-URL: Homepage, https://smkent.github.io/copier-python
6
6
  Project-URL: Repository, https://github.com/smkent/copier-python
@@ -1141,76 +1141,7 @@
1141
1141
 
1142
1142
  '''
1143
1143
  # ---
1144
- # name: test_workflows_release[no_pypi]
1145
- '''
1146
- name: Release
1147
-
1148
- on:
1149
- push:
1150
- tags:
1151
- - v[0-9]*.[0-9]*
1152
-
1153
- jobs:
1154
- build:
1155
- name: Build distribution
1156
- runs-on: ubuntu-latest
1157
- env:
1158
- UV_PYTHON: '3.14'
1159
- steps:
1160
- - name: 💾 Check out repository
1161
- uses: actions/checkout@v7
1162
- with:
1163
- fetch-depth: 0
1164
-
1165
- - name: 📦 Cache uv managed packages
1166
- uses: actions/cache@v6
1167
- with:
1168
- path: ~/.cache/uv
1169
- key: uv-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'uv.lock') }}
1170
- restore-keys: |
1171
- uv-${{ runner.os }}-
1172
-
1173
- - name: 🍳 Set up mise
1174
- uses: jdx/mise-action@v5
1175
- with:
1176
- cache: true
1177
- install: true
1178
-
1179
- - name: 📦 Build package
1180
- run: mise run build
1181
-
1182
- - name: 🔼 Upload artifact
1183
- uses: actions/upload-artifact@v7
1184
- with:
1185
- name: dist
1186
- path: dist/
1187
-
1188
- release:
1189
- name: Create GitHub release
1190
- needs: build
1191
- runs-on: ubuntu-latest
1192
- permissions:
1193
- contents: write
1194
- steps:
1195
- - name: 💾 Check out repository
1196
- uses: actions/checkout@v7
1197
- with:
1198
- fetch-depth: 0
1199
-
1200
- - name: 🔽 Download artifact
1201
- uses: actions/download-artifact@v8
1202
- with:
1203
- name: dist
1204
- path: dist/
1205
-
1206
- - name: 🏷️ Create GitHub release
1207
- run: gh release create ${{ github.ref_name }} dist/* --generate-notes
1208
- env:
1209
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1210
-
1211
- '''
1212
- # ---
1213
- # name: test_workflows_release[pypi]
1144
+ # name: test_workflows_release
1214
1145
  '''
1215
1146
  name: Release
1216
1147
 
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  import pytest
7
7
  from syrupy.assertion import SnapshotAssertion
8
8
 
9
- from tests.utils import license_choices
9
+ from tests.utils import choices
10
10
 
11
11
 
12
12
  @pytest.mark.parametrize(
@@ -23,7 +23,7 @@ def test_contributing_features(
23
23
  assert (rendered / "CONTRIBUTING.md").read_text() == snapshot
24
24
 
25
25
 
26
- @pytest.mark.parametrize("copyright_license", license_choices.values())
26
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
27
27
  def test_contributing_license(
28
28
  render_template: Callable[..., Path],
29
29
  snapshot: SnapshotAssertion,
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  import pytest
7
7
  from syrupy.assertion import SnapshotAssertion
8
8
 
9
- from tests.utils import license_choices
9
+ from tests.utils import choices
10
10
 
11
11
 
12
12
  @pytest.mark.parametrize(
@@ -66,7 +66,7 @@ def test_docs_development_features(
66
66
  ).read_text() == snapshot
67
67
 
68
68
 
69
- @pytest.mark.parametrize("copyright_license", license_choices.values())
69
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
70
70
  def test_docs_license(
71
71
  render_template: Callable[..., Path],
72
72
  snapshot: SnapshotAssertion,
@@ -7,10 +7,10 @@ import pytest
7
7
  import yaml
8
8
  from syrupy.assertion import SnapshotAssertion
9
9
 
10
- from tests.utils import TEMPLATE_ROOT, license_choices
10
+ from tests.utils import TEMPLATE_ROOT, choices
11
11
 
12
12
 
13
- @pytest.mark.parametrize("copyright_license", license_choices.values())
13
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
14
14
  def test_license(
15
15
  render_template: Callable[..., Path],
16
16
  snapshot: SnapshotAssertion,
@@ -22,27 +22,6 @@ def test_license(
22
22
  assert (rendered / name).read_text() == snapshot
23
23
 
24
24
 
25
- @pytest.mark.parametrize("copyright_license", license_choices.values())
26
- def test_license_files(
27
- render_template: Callable[..., Path], copyright_license: str
28
- ) -> None:
29
- if copyright_license.startswith("LGPL-"):
30
- expected = ["COPYING", "COPYING.LESSER"]
31
- elif "GPL-" in copyright_license:
32
- expected = ["COPYING"]
33
- else:
34
- expected = ["LICENSE"]
35
- rendered = render_template(copyright_license=copyright_license)
36
- assert (
37
- sorted(
38
- p.name
39
- for p in rendered.iterdir()
40
- if p.name in {"LICENSE", "COPYING", "COPYING.LESSER"}
41
- )
42
- == expected
43
- )
44
-
45
-
46
25
  @pytest.mark.parametrize("project_type", ["application", "library"])
47
26
  def test_license_default(
48
27
  render_template: Callable[..., Path], project_type: str
@@ -56,7 +35,7 @@ def test_license_default(
56
35
  )
57
36
 
58
37
 
59
- @pytest.mark.parametrize("copyright_license", license_choices.values())
38
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
60
39
  def test_license_choices_have_templates(copyright_license: str) -> None:
61
40
  assert (
62
41
  TEMPLATE_ROOT / "includes" / "licenses" / copyright_license
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  import pytest
7
7
  from syrupy.assertion import SnapshotAssertion
8
8
 
9
- from tests.utils import license_choices
9
+ from tests.utils import choices
10
10
 
11
11
 
12
12
  @pytest.mark.parametrize("project_visibility", ["public", "private"])
@@ -63,7 +63,7 @@ def test_pyproject_versions(
63
63
  assert (rendered / "pyproject.toml").read_text() == snapshot
64
64
 
65
65
 
66
- @pytest.mark.parametrize("copyright_license", license_choices.values())
66
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
67
67
  def test_pyproject_licenses(
68
68
  render_template: Callable[..., Path],
69
69
  snapshot: SnapshotAssertion,
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  import pytest
7
7
  from syrupy.assertion import SnapshotAssertion
8
8
 
9
- from tests.utils import license_choices
9
+ from tests.utils import choices
10
10
 
11
11
 
12
12
  @pytest.mark.parametrize(
@@ -41,7 +41,7 @@ def test_readme_features(
41
41
 
42
42
 
43
43
  @pytest.mark.parametrize("project_visibility", ["public", "private"])
44
- @pytest.mark.parametrize(("copyright_license"), license_choices.values())
44
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
45
45
  def test_readme_project_visibility(
46
46
  render_template: Callable[..., Path],
47
47
  snapshot: SnapshotAssertion,
@@ -0,0 +1,156 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from dataclasses import dataclass, field
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ import pytest
8
+
9
+ from tests.utils import choices
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Callable
13
+ from pathlib import Path
14
+
15
+
16
+ @dataclass
17
+ class StructureTestCase:
18
+ extra_data: dict[str, Any] = field(default_factory=dict)
19
+ expected_present: set[str] = field(default_factory=set)
20
+ expected_absent: set[str] = field(default_factory=set)
21
+
22
+ def expect_if(self, present: bool, *items: str) -> None: # noqa: FBT001
23
+ if present:
24
+ self.expected_present |= set(items)
25
+ else:
26
+ self.expected_absent |= set(items)
27
+
28
+ def run(self, render_template: Callable[..., Path]) -> None:
29
+ rendered = render_template(**self.extra_data)
30
+ for path in self.expected_present:
31
+ assert (rendered / path).exists(), f"{path!r} should exist"
32
+ for path in self.expected_absent:
33
+ assert not (rendered / path).exists(), f"{path!r} should be absent"
34
+
35
+
36
+ @dataclass
37
+ class StructureTest:
38
+ render_template: Callable[..., Path] = field(repr=False)
39
+
40
+ def __call__(self, case: StructureTestCase) -> None:
41
+ case.run(self.render_template)
42
+
43
+
44
+ @pytest.fixture
45
+ def structure_test(
46
+ render_template: Callable[..., Path],
47
+ ) -> StructureTest:
48
+ return StructureTest(render_template=render_template)
49
+
50
+
51
+ @pytest.mark.parametrize("project_type", choices["project_type"])
52
+ @pytest.mark.parametrize("project_visibility", choices["project_visibility"])
53
+ @pytest.mark.parametrize(
54
+ "enable_coverage",
55
+ [pytest.param(True, id="coverage"), pytest.param(False, id="no_coverage")],
56
+ )
57
+ @pytest.mark.parametrize(
58
+ "enable_pypi",
59
+ [pytest.param(True, id="pypi"), pytest.param(False, id="no_pypi")],
60
+ )
61
+ @pytest.mark.parametrize(
62
+ "enable_container",
63
+ [
64
+ pytest.param(True, id="container"),
65
+ pytest.param(False, id="no_container"),
66
+ ],
67
+ )
68
+ @pytest.mark.parametrize(
69
+ "enable_docs",
70
+ [pytest.param(True, id="docs"), pytest.param(False, id="no_docs")],
71
+ )
72
+ def test_structure(
73
+ structure_test: StructureTest,
74
+ project_type: str,
75
+ project_visibility: str,
76
+ *,
77
+ enable_coverage: bool,
78
+ enable_pypi: bool,
79
+ enable_container: bool,
80
+ enable_docs: bool,
81
+ ) -> None:
82
+ case = StructureTestCase(
83
+ extra_data={
84
+ "project_type": project_type,
85
+ "project_visibility": project_visibility,
86
+ "enable_container": enable_container,
87
+ "enable_coverage": enable_coverage,
88
+ "enable_pypi": enable_pypi,
89
+ "enable_docs": enable_docs,
90
+ },
91
+ expected_present={
92
+ ".gitignore",
93
+ ".pre-commit-config.yaml",
94
+ "README.md",
95
+ "pyproject.toml",
96
+ "renovate.json",
97
+ },
98
+ )
99
+ case.expect_if(
100
+ project_visibility == "public",
101
+ ".github/workflows/audit.yaml",
102
+ ".github/workflows/ci.yaml",
103
+ "CONTRIBUTING.md",
104
+ )
105
+ case.expect_if(
106
+ project_visibility == "public" and enable_pypi,
107
+ ".github/workflows/release.yaml",
108
+ )
109
+ case.expect_if(
110
+ enable_container,
111
+ "Dockerfile",
112
+ ".dockerignore",
113
+ )
114
+ case.expect_if(
115
+ project_visibility == "public" and enable_container,
116
+ ".github/workflows/container.yaml",
117
+ ".github/workflows/ghcr.yaml",
118
+ )
119
+ case.expect_if(
120
+ enable_docs,
121
+ "docs",
122
+ "docs/api.md",
123
+ "docs/contributing.md",
124
+ "docs/development/requirements.md",
125
+ "docs/development/updates.md",
126
+ "docs/development/workflow.md",
127
+ "docs/index.md",
128
+ "docs/license.md",
129
+ "zensical.toml",
130
+ )
131
+ case.expect_if(
132
+ project_visibility == "public" and enable_docs,
133
+ ".github/workflows/docs.yaml",
134
+ "docs/setup.md",
135
+ "docs/releasing.md",
136
+ )
137
+ case.expect_if(
138
+ project_type == "application" and enable_container, "compose.yaml"
139
+ )
140
+ structure_test(case)
141
+
142
+
143
+ @pytest.mark.parametrize("copyright_license", choices["copyright_license"])
144
+ def test_structure_license(
145
+ structure_test: StructureTest,
146
+ copyright_license: str,
147
+ ) -> None:
148
+ case = StructureTestCase(
149
+ extra_data={"copyright_license": copyright_license}
150
+ )
151
+ case.expect_if(not re.match(r"^[AL]?GPL-", copyright_license), "LICENSE")
152
+ case.expect_if(bool(re.match(r"^[AL]?GPL-", copyright_license)), "COPYING")
153
+ case.expect_if(
154
+ bool(re.match(r"^LGPL-", copyright_license)), "COPYING.LESSER"
155
+ )
156
+ structure_test(case)
@@ -54,20 +54,14 @@ def test_workflows_ci_versions(
54
54
  ).read_text() == snapshot
55
55
 
56
56
 
57
- @pytest.mark.parametrize(
58
- "enable_pypi",
59
- [pytest.param(True, id="pypi"), pytest.param(False, id="no_pypi")],
60
- )
61
57
  def test_workflows_release(
62
58
  render_template: Callable[..., Path],
63
59
  snapshot: SnapshotAssertion,
64
- *,
65
- enable_pypi: bool,
66
60
  ) -> None:
67
61
  rendered = render_template(
68
62
  project_type="application",
69
63
  project_visibility="public",
70
- enable_pypi=enable_pypi,
64
+ enable_pypi=True,
71
65
  )
72
66
  assert (
73
67
  rendered / ".github" / "workflows" / "release.yaml"
@@ -69,10 +69,12 @@ class DisallowCallable:
69
69
  self.mock_attr.assert_not_called()
70
70
 
71
71
 
72
- def _load_license_choices() -> dict[str, str]:
73
- return yaml.safe_load((TEMPLATE_ROOT / "copier.yaml").read_text())[
74
- "copyright_license"
75
- ]["choices"]
76
-
77
-
78
- license_choices = _load_license_choices()
72
+ choices = {
73
+ k: list(choices.values()) if isinstance(choices, dict) else choices
74
+ for k, v in yaml.safe_load(
75
+ (TEMPLATE_ROOT / "copier.yaml").read_text()
76
+ ).items()
77
+ if isinstance(v, dict)
78
+ and (choices := v.get("choices"))
79
+ and isinstance(choices, (dict, list))
80
+ }
@@ -1,107 +0,0 @@
1
- """Tests for rendered project file presence and absence."""
2
-
3
- from collections.abc import Callable
4
- from pathlib import Path
5
- from typing import Any
6
-
7
- import pytest
8
-
9
-
10
- @pytest.mark.parametrize(
11
- ("extra_data", "expected_present", "expected_absent"),
12
- [
13
- pytest.param(
14
- {
15
- "project_type": "library",
16
- "enable_coverage": False,
17
- "enable_pypi": False,
18
- "enable_docs": False,
19
- },
20
- [
21
- "pyproject.toml",
22
- "README.md",
23
- "CONTRIBUTING.md",
24
- "LICENSE",
25
- ".gitignore",
26
- ".pre-commit-config.yaml",
27
- "renovate.json",
28
- ".github/workflows/ci.yaml",
29
- ".github/workflows/audit.yaml",
30
- ".github/workflows/release.yaml",
31
- ],
32
- [
33
- "docs",
34
- "Dockerfile",
35
- ".dockerignore",
36
- "compose.yaml",
37
- "zensical.toml",
38
- ".github/workflows/docs.yaml",
39
- ".github/workflows/container.yaml",
40
- ".github/workflows/ghcr.yaml",
41
- ],
42
- id="public_library_minimal",
43
- ),
44
- pytest.param(
45
- {"project_visibility": "private"},
46
- [],
47
- [".github", "CONTRIBUTING.md"],
48
- id="private",
49
- ),
50
- pytest.param(
51
- {"enable_pypi": True},
52
- [".github/workflows/release.yaml"],
53
- [],
54
- id="pypi",
55
- ),
56
- pytest.param(
57
- {"enable_container": True, "project_type": "library"},
58
- [
59
- "Dockerfile",
60
- ".dockerignore",
61
- ".github/workflows/container.yaml",
62
- ".github/workflows/ghcr.yaml",
63
- ],
64
- ["compose.yaml"],
65
- id="container_library",
66
- ),
67
- pytest.param(
68
- {"enable_container": True, "project_type": "application"},
69
- ["Dockerfile", ".dockerignore", "compose.yaml"],
70
- [],
71
- id="container_application",
72
- ),
73
- pytest.param(
74
- {
75
- "project_visibility": "public",
76
- "project_type": "application",
77
- "enable_docs": True,
78
- "enable_pypi": True,
79
- "enable_container": True,
80
- "enable_coverage": True,
81
- },
82
- [
83
- "docs",
84
- "docs/setup.md",
85
- "docs/releasing.md",
86
- "docs/development/requirements.md",
87
- "docs/development/workflow.md",
88
- "docs/development/updates.md",
89
- "zensical.toml",
90
- ".github/workflows/docs.yaml",
91
- ],
92
- [],
93
- id="docs_application",
94
- ),
95
- ],
96
- )
97
- def test_structure(
98
- render_template: Callable[..., Path],
99
- extra_data: dict[str, Any],
100
- expected_present: list[str],
101
- expected_absent: list[str],
102
- ) -> None:
103
- rendered = render_template(**extra_data)
104
- for path in expected_present:
105
- assert (rendered / path).exists(), f"{path!r} should exist"
106
- for path in expected_absent:
107
- assert not (rendered / path).exists(), f"{path!r} should be absent"
File without changes
File without changes
File without changes