Skip to content

Commit 3ecdcca

Browse files
authored
feat: add support for _extra_tasks in CTT TOML configuration (#36)
1 parent 0165e12 commit 3ecdcca

File tree

6 files changed

+52
-9
lines changed

6 files changed

+52
-9
lines changed

copier_template_tester/_write_output.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,13 @@ def _remove_readonly(func, path: str, _excinfo) -> None: # noqa: ANN001
138138
func(path)
139139

140140

141-
def write_output(*, src_path: Path, dst_path: Path, data: dict[str, bool | int | float | str | None], **kwargs) -> None:
141+
def write_output(
142+
*,
143+
src_path: Path,
144+
dst_path: Path, data: dict[str, bool | int | float | str | None],
145+
extra_tasks: list[str | list[str] | dict] | None = None,
146+
**kwargs,
147+
) -> None:
142148
"""Copy the specified directory to the target location with provided data.
143149
144150
kwargs documentation: https://github.com/copier-org/copier/blob/103828b59fd9eb671b5ffa909004d1577742300b/copier/main.py#L86-L173
@@ -153,7 +159,10 @@ def write_output(*, src_path: Path, dst_path: Path, data: dict[str, bool | int |
153159
kwargs.setdefault('quiet', False)
154160
kwargs.setdefault('unsafe', True)
155161
kwargs.setdefault('vcs_ref', 'HEAD')
156-
copier.run_copy(str(src_path), dst_path, **kwargs)
162+
163+
with copier.Worker(src_path=str(src_path), dst_path=Path(dst_path), **kwargs) as worker:
164+
worker.template.config_data['tasks'] = worker.template.config_data.get('tasks', []) + extra_tasks
165+
worker.run_copy()
157166

158167
# Remove any .git directory created by copier script
159168
git_path = dst_path / '.git'

copier_template_tester/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ def run(*, base_dir: Path | None = None, check_untracked: bool = False) -> None:
4141
output_path = base_dir / key
4242
paths.add(output_path)
4343
logger.text(f'Using `copier` to create: {key}')
44-
write_output(src_path=input_path, dst_path=base_dir / output_path, data=defaults | data)
44+
data_with_defaults = defaults | data
45+
extra_tasks = data_with_defaults.pop('_extra_tasks', [])
46+
write_output(
47+
src_path=input_path, dst_path=base_dir / output_path, data=data_with_defaults, extra_tasks=extra_tasks,
48+
)
4549

4650
if check_untracked: # pragma: no cover
4751
check_for_untracked(base_dir)

docs/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ package_name = "testing-no-all"
3737
include_all = false
3838
```
3939

40+
#### Extra tasks
41+
42+
Anything in the `_extra_tasks` key will be run after that project is generated. This is useful for running tests or other tasks that are not part of the copier template.
43+
44+
```toml
45+
[defaults]
46+
_extra_tasks = [
47+
"pre-commit run --all-files",
48+
]
49+
50+
[output.".ctt/also-run-pytest-here"]
51+
_extra_tasks = [
52+
"poetry run pytest",
53+
]
54+
```
55+
4056
### Pre-Commit Hook
4157

4258
First, add this section to your `.pre-commit-config.yml` file:

docs/docs/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Unreleased
22

3+
### Feat
4+
5+
- add option to run extra tasks in each generated project
6+
37
## 2.1.3 (2024-07-08)
48

59
### Fix

tests/data/copier_demo/ctt.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Configuration for: https://github.com/KyleKing/copier-template-tester
22

33
[defaults]
4+
_extra_tasks = [
5+
"echo task_string",
6+
["echo", "task_list"],
7+
{command = "echo task_dict"},
8+
]
49
project_name = "placeholder"
510

611
[output.".ctt/no_all"]

tests/test_main.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
def test_main_with_copier_mock(monkeypatch, base_dir: Path) -> None:
2020
"""Only necessary for coverage metrics, but the .ctt/* files must exist."""
2121

22-
def _run_copy(src_path: str, dst_path: Path, **kwargs) -> None:
22+
def _run_copy(worker) -> None:
2323
pass
2424

25-
monkeypatch.setattr(copier, 'run_copy', _run_copy)
25+
monkeypatch.setattr(copier.Worker, 'run_copy', _run_copy)
2626

2727
run(base_dir=base_dir)
2828

@@ -42,26 +42,31 @@ def check_run_ctt(*, shell: Subprocess, cwd: Path, subdirname: str) -> set[Path]
4242
'*Copying from template*',
4343
])
4444
# Check a few of the created files:
45-
return {pth.relative_to(cwd) for pth in (cwd / '.ctt').rglob('*.*') if pth.is_file()}
45+
return {pth.relative_to(cwd) for pth in (cwd / '.ctt').rglob('*.*') if pth.is_file()}, ret.stdout
4646

4747

4848
def test_main(shell: Subprocess) -> None:
49-
paths = check_run_ctt(shell=shell, cwd=DEMO_DIR, subdirname='no_all')
49+
paths, stdout = check_run_ctt(shell=shell, cwd=DEMO_DIR, subdirname='no_all')
5050

5151
assert Path('.ctt/no_all/README.md') in paths
5252
assert Path('.ctt/no_all/.copier-answers.testing_no_all.yml') in paths
5353
assert Path('.ctt/no_all/.copier-answers.yml') not in paths
54+
stdout.matcher.fnmatch_lines_random([
55+
'task_string',
56+
'task_list',
57+
'task_dict',
58+
])
5459

5560

5661
def test_no_answer_file_dir(shell: Subprocess) -> None:
57-
paths = check_run_ctt(shell=shell, cwd=NO_ANSWER_FILE_DIR, subdirname='no_answers_file')
62+
paths, _stdout = check_run_ctt(shell=shell, cwd=NO_ANSWER_FILE_DIR, subdirname='no_answers_file')
5863

5964
assert Path('.ctt/no_answers_file/README.md') in paths
6065
assert not [*Path('.ctt/no_answers_file').rglob('.copier-answers*')]
6166

6267

6368
def test_with_include_dir(shell: Subprocess) -> None:
64-
paths = check_run_ctt(shell=shell, cwd=WITH_INCLUDE_DIR, subdirname='copier_include')
69+
paths, _stdout = check_run_ctt(shell=shell, cwd=WITH_INCLUDE_DIR, subdirname='copier_include')
6570

6671
assert Path('.ctt/copier_include/script.py') in paths
6772

0 commit comments

Comments
 (0)