1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
from __future__ import annotations
import itertools
import os
from typing import TYPE_CHECKING
import pytest
from semantic_release.changelog.template import environment, recursive_render
if TYPE_CHECKING:
from pathlib import Path
from tests.fixtures.example_project import ExProjectDir
NORMAL_TEMPLATE_SRC = """---
content:
- a string
- ["a nested list"]
vars:
# a comment
hello: {{ "world" | upper }}
"""
NORMAL_TEMPLATE_RENDERED = """---
content:
- a string
- ["a nested list"]
vars:
# a comment
hello: WORLD
"""
PLAINTEXT_FILE_CONTENT = """
I should not be rendered as a template.
{{ "this string should be untouched" | upper }}
"""
def _strip_trailing_j2(path: Path) -> Path:
if path.name.endswith(".j2"):
return path.with_name(path.name[:-3])
return path
@pytest.fixture
def normal_template(example_project_template_dir: Path) -> Path:
template = example_project_template_dir / "normal.yaml.j2"
template.parent.mkdir(parents=True, exist_ok=True)
template.write_text(NORMAL_TEMPLATE_SRC)
return template
@pytest.fixture
def long_directory_path(example_project_template_dir: Path) -> Path:
# NOTE: fixture enables using Path rather than
# constant string, so no issue with / vs \ on Windows
return example_project_template_dir / "long" / "dir" / "path"
@pytest.fixture
def deeply_nested_file(long_directory_path: Path) -> Path:
file = long_directory_path / "buried.txt"
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text(PLAINTEXT_FILE_CONTENT)
return file
@pytest.fixture
def hidden_file(example_project_template_dir: Path) -> Path:
file = example_project_template_dir / ".hidden"
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text("I shouldn't be present")
return file
@pytest.fixture
def directory_path_with_hidden_subfolder(example_project_template_dir: Path) -> Path:
return example_project_template_dir / "path" / ".subfolder" / "hidden"
@pytest.fixture
def excluded_file(directory_path_with_hidden_subfolder: Path) -> Path:
file = directory_path_with_hidden_subfolder / "excluded.txt"
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text("I shouldn't be present")
return file
@pytest.mark.usefixtures(excluded_file.__name__)
def test_recursive_render(
init_example_project: None,
example_project_dir: Path,
example_project_template_dir: Path,
normal_template,
deeply_nested_file,
hidden_file,
):
tmpl_dir = str(example_project_template_dir.resolve())
env = environment(template_dir=tmpl_dir)
preexisting_paths = set(example_project_dir.rglob("**/*"))
recursive_render(
template_dir=example_project_template_dir.resolve(),
environment=env,
_root_dir=str(example_project_dir.resolve()),
)
rendered_normal_template = _strip_trailing_j2(
example_project_dir / normal_template.relative_to(example_project_template_dir)
)
assert rendered_normal_template.exists()
assert rendered_normal_template.read_text() == NORMAL_TEMPLATE_RENDERED
rendered_deeply_nested = example_project_dir / deeply_nested_file.relative_to(
example_project_template_dir
)
assert rendered_deeply_nested.exists()
assert rendered_deeply_nested.read_text() == PLAINTEXT_FILE_CONTENT
rendered_hidden = example_project_dir / hidden_file.relative_to(
example_project_template_dir
)
assert not rendered_hidden.exists()
assert not (example_project_dir / "path").exists()
assert set(example_project_dir.rglob("**/*")) == preexisting_paths.union(
example_project_dir / p
for t in (
rendered_normal_template,
rendered_deeply_nested,
)
for p in itertools.accumulate(
t.relative_to(example_project_dir).parts, func=lambda *a: os.sep.join(a)
)
)
@pytest.fixture
def dotfolder_template_dir(example_project_dir: ExProjectDir) -> Path:
return example_project_dir / ".templates/.psr-templates"
@pytest.fixture
def dotfolder_template(
init_example_project: None, dotfolder_template_dir: Path
) -> Path:
tmpl = dotfolder_template_dir / "template.txt"
tmpl.parent.mkdir(parents=True, exist_ok=True)
tmpl.write_text("I am a template")
return tmpl
def test_recursive_render_with_top_level_dotfolder(
init_example_project: None,
example_project_dir: ExProjectDir,
dotfolder_template: Path,
dotfolder_template_dir: Path,
):
preexisting_paths = set(example_project_dir.rglob("**/*"))
env = environment(template_dir=dotfolder_template_dir.resolve())
recursive_render(
template_dir=dotfolder_template_dir.resolve(),
environment=env,
_root_dir=example_project_dir.resolve(),
)
rendered_template = example_project_dir / dotfolder_template.name
assert rendered_template.exists()
assert set(example_project_dir.rglob("**/*")) == preexisting_paths.union(
{example_project_dir / rendered_template}
)
|