From d2de5352670c9b0d353cddeb35ee22d6af198426 Mon Sep 17 00:00:00 2001 From: Craig Burdulis Date: Sat, 25 Mar 2023 02:59:55 -0400 Subject: [PATCH] feat: allow templating `_answers_file` setting (#1027) Co-authored-by: Ethan Barker --- copier/main.py | 4 +- tests/test_answersfile_templating.py | 74 ++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 tests/test_answersfile_templating.py diff --git a/copier/main.py b/copier/main.py index 89dca72da..56f983a5c 100644 --- a/copier/main.py +++ b/copier/main.py @@ -410,7 +410,9 @@ def answers_relpath(self) -> Path: 2. Template default. 3. Copier default. """ - return self.answers_file or self.template.answers_relpath + path = self.answers_file or self.template.answers_relpath + template = self.jinja_env.from_string(str(path)) + return Path(template.render(**self.answers.combined)) @cached_property def all_exclusions(self) -> StrSeq: diff --git a/tests/test_answersfile_templating.py b/tests/test_answersfile_templating.py new file mode 100644 index 000000000..f05a8f288 --- /dev/null +++ b/tests/test_answersfile_templating.py @@ -0,0 +1,74 @@ +import pytest + +import copier +from copier.user_data import load_answersfile_data + +from .helpers import build_file_tree + + +@pytest.fixture(scope="module") +def template_path(tmp_path_factory) -> str: + root = tmp_path_factory.mktemp("template") + build_file_tree( + { + root + / "{{ _copier_conf.answers_file }}.jinja": """\ + # Changes here will be overwritten by Copier + {{ _copier_answers|to_nice_yaml }} + """, + root + / "copier.yml": """\ + _answers_file: ".copier-answers-{{ module_name }}.yml" + + module_name: + type: str + """, + } + ) + return str(root) + + +@pytest.mark.parametrize("answers_file", [None, ".changed-by-user.yml"]) +def test_answersfile_templating(template_path, tmp_path, answers_file): + """ + Test copier behaves properly when _answers_file contains a template + + Checks that template is resolved successfully and that a subsequent + copy that resolves to a different answers file doesn't clobber the + old answers file. + """ + copier.copy( + template_path, + tmp_path, + {"module_name": "mymodule"}, + answers_file=answers_file, + defaults=True, + overwrite=True, + ) + first_answers_file = ( + ".copier-answers-mymodule.yml" + if answers_file is None + else ".changed-by-user.yml" + ) + assert (tmp_path / first_answers_file).exists() + answers = load_answersfile_data(tmp_path, first_answers_file) + assert answers["module_name"] == "mymodule" + + copier.copy( + template_path, + tmp_path, + {"module_name": "anothermodule"}, + defaults=True, + overwrite=True, + ) + + # Assert second one created + second_answers_file = ".copier-answers-anothermodule.yml" + assert (tmp_path / second_answers_file).exists() + answers = load_answersfile_data(tmp_path, second_answers_file) + assert answers["module_name"] == "anothermodule" + + # Assert first one still exists + assert (tmp_path / first_answers_file).exists() + answers = load_answersfile_data(tmp_path, first_answers_file) + assert answers["module_name"] == "mymodule"