wads.templating¶
Declarative, template-source-driven generation engine.
The core idea (issue #32, originally #3): a template source is any
Mapping[str, str] mapping a relative path to template content. Three
concrete kinds are supported, exactly matching the original spec:
an in-memory mapping – a plain
dict(or one loaded from JSON/YAML),a local filesystem folder –
FilesystemTemplateSource,a remote folder hosted on GitHub –
GithubTemplateSource.
Because a template source is just a Mapping, any key-value store (including
dol-style stores) can be used as one without wads depending on it.
Rendering is a thin layer over Jinja2 using custom delimiters so template
markup never collides with GitHub Actions ${{ ... }} expressions or shell
${...}:
Jinja2 default |
wads delimiter |
|---|---|
|
|
|
|
|
|
A small set of render strategies lets the engine reproduce historical wads
output exactly: copy (verbatim), jinja (Jinja2 with the delimiters
above), and placeholder (legacy #TOKEN# substitution kept for old CI
templates).
An Artifact declaratively describes one generated file: its target
path, how its content is produced, and an optional condition. A profile is
just a list of artifacts; generate() walks one and writes the files,
honoring an overwrite set and recording actions on an optional tracker.
>>> source = {"greeting.txt": "Hello << name >>!"}
>>> render(source["greeting.txt"], {"name": "world"})
'Hello world!'
Module Attributes
Jinja2 delimiters chosen to avoid colliding with ``${{ . |
Functions
|
Legacy |
|
Apply a list of |
|
Build a Jinja2 environment with wads's custom delimiters. |
|
Render |
Classes
|
One file to generate within a project. |
|
A template source backed by a local folder. |
|
Outcome of |
|
A template source backed by a folder in a GitHub repository. |
- class wads.templating.Artifact(target, content, when=None, binary=False)[source]¶
Bases:
objectOne file to generate within a project.
- Parameters:
target (
str) – relative path of the file in the generated project.content (
Callable[[Mapping],Optional[str]]) – a callablecontext -> str | Noneproducing the file text (Noneto skip). Use thefrom_*constructors for the commoncopy/jinja/placeholderstrategies.when (
Optional[Callable[[Mapping],bool]]) – optional predicatecontext -> boolgating generation.binary (
bool) – if True,contentreturnsbytesand is written binary.
- classmethod from_copy(target, source_key, source, **kw)[source]¶
Artifact that copies
source[source_key]verbatim.
- class wads.templating.FilesystemTemplateSource(root, *, encoding='utf-8')[source]¶
Bases:
MappingA template source backed by a local folder.
Keys are POSIX-style relative paths of the files under
root; values are the (text) file contents, read lazily on access.>>> import tempfile, os >>> d = tempfile.mkdtemp() >>> _ = open(os.path.join(d, "a.txt"), "w").write("A") >>> src = FilesystemTemplateSource(d) >>> src["a.txt"] 'A' >>> list(src) ['a.txt']
- class wads.templating.GenerationResult(added=<factory>, skipped=<factory>, errored=<factory>)[source]¶
Bases:
objectOutcome of
generate().
- class wads.templating.GithubTemplateSource(repo, *, ref='master', subdir='')[source]¶
Bases:
MappingA template source backed by a folder in a GitHub repository.
Files are fetched lazily from
raw.githubusercontent.com. Uses the standard library only (norequestsdependency) so it stays usable in a light install.- Parameters:
Listing (
__iter__/__len__) uses the GitHub trees API and is only needed when enumerating; directsource[key]access does not list.
- wads.templating.JINJA_DELIMITERS = {'block_end_string': '%>', 'block_start_string': '<%', 'comment_end_string': '#>', 'comment_start_string': '<#', 'variable_end_string': '>>', 'variable_start_string': '<<'}¶
Jinja2 delimiters chosen to avoid colliding with
${{ ... }}(GitHub Actions) and${...}(shell).
- wads.templating.apply_placeholders(content, mapping)[source]¶
Legacy
#TOKEN#substitution used by the older CI templates.- Return type:
>>> apply_placeholders("name=#NAME#", {"#NAME#": "wads"}) 'name=wads'
- wads.templating.generate(target_dir, artifacts, context, *, overwrite=(), on_add=None, on_skip=None, on_error=None)[source]¶
Apply a list of
Artifacttotarget_dir.An artifact is written when its target does not exist or its target is in
overwrite. Parent directories are created as needed. Each action is reported through the optionalon_*callbacks and accumulated in the returnedGenerationResult.- Return type: