Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Document the context hook extension #641

Merged
merged 13 commits into from
Apr 24, 2022
Merged
6 changes: 6 additions & 0 deletions docs/comparisons.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ docs! We don't want to be biased, but it's easy that we tend to be:
| Requires programming | No | No | Yes, JS |
| Requires templates to have a suffix | Yes by default, configurable[^3] | No, not configurable | You choose |
| Task hooks | Yes | Yes | Yes |
| Context hooks | Yes[^5] | Yes | ? |
| Template in a subfolder | Not required, but you choose | Yes, required | Yes, required |
| Template package format | Git repo[^2], Git bundle, folder | Git or Mercurial repo, Zip file | NPM package |
| Template updates | **Yes**[^4] | No | No |
Expand All @@ -49,3 +50,8 @@ docs! We don't want to be biased, but it's easy that we tend to be:
[^4]:
Only for git templates, because Copier uses git tags to obtain available versions
and extract smart diffs between them.

[^5]: Context hooks are provided through the [`ContextHook` extension][context-hook].

[context-hook]:
https://github.com/copier-org/copier-templates-extensions#context-hook-extension
6 changes: 4 additions & 2 deletions docs/configuring.md
Original file line number Diff line number Diff line change
Expand Up @@ -699,9 +699,11 @@ on them, so they are always installed when Copier is installed.
provides a `slugify` filter using
[python-slugify](https://github.com/un33k/python-slugify).

- [`copier_templates_extensions.TemplateExtensionLoader`](https://github.com/pawamoy/copier-templates-extensions):
- [`copier_templates_extensions.TemplateExtensionLoader`](https://github.com/copier-org/copier-templates-extensions):
enhances the extension loading mecanism to allow templates writers to put their
extensions directly in their templates.
extensions directly in their templates. It also allows to modify the rendering context
(the Jinja variables that you can use in your templates) before
rendering templates, see [using a context hook](../faq#how-can-i-alter-the-context-before-rendering-the-project).
- [`jinja_markdown.MarkdownExtension`](https://github.com/jpsca/jinja-markdown):
provides a `markdown` tag that will render Markdown to HTML using
[PyMdown extensions](https://facelessuser.github.io/pymdown-extensions/).
Expand Down
100 changes: 100 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Frequently Asked Questions

## How can I alter the context before rendering the project?

Similar questions:

- **How can I add/remove variables to/from the rendering context?**
- **How to infer context variables based on the users answers, without prompting
users?**

Answer:

**Use the [`ContextHook` extension][context-hook].**

The [`ContextHook` extension][context-hook] lets you modify the context used to render
templates, so that you can add, change or remove variables.

[context-hook]:
https://github.com/copier-org/copier-templates-extensions#context-hook-extension

In order for Copier to be able to load and use the extension when generating a project,
it must be installed alongside Copier itself. More details in the
[`jinja_extensions` docs](#jinja_extensions).

You can then configure your Jinja extensions in Copier's configuration file:

```yaml title="copier.yaml"
_jinja_extensions:
- copier_templates_extensions.TemplateExtensionLoader
- extensions/context.py:ContextUpdater
```

Following this example, you are supposed to provide a `context.py` file in the
`extensions` folder at the root of your template to modify the context. If for example
your `copier.yaml` contains a multiple-choice variable like this:

```yaml title="copier.yaml"
flavor:
type: str
choices:
- Docker
- Instances
- Kubernetes
- None
```

The `context.py` file contains your context hook which could look like:

```python title="extensions/context.py"
from copier_templates_extensions import ContextHook


class ContextUpdater(ContextHook):
def hook(self, context):
flavor = context["flavor"] # user's answer to the "flavor" question
return {
"isDocker": flavor == "docker"
"isK8s": flavor == "kubernetes"
"isInstances": flavor == "instances"
"isLite": flavor == "none"
"isNotDocker": flavor != "docker"
"isNotK8s": flavor != "kubernetes"
"isNotInstances": flavor != "instances"
"isNotLite": flavor != "none"
"hasContainers": flavor in {"docker", "kubernetes"}
}
```

Before rendering each templated file/folder, the context will be updated with this new
context object that you return from the hook. If you wish to update the context in-place
rather than update it, set the `update` class attribute to false:

```python title="extensions/context.py"
from copier_templates_extensions import ContextHook


class ContextUpdater(ContextHook):
update = False

def hook(self, context):
flavor = context["flavor"] # user's answer to the "flavor" question

context["isDocker"] = flavor == "docker"
context["isK8s"] = flavor == "kubernetes"
context["isInstances"] = flavor == "instances"
context["isLite"] = flavor == "none"

context["isNotDocker"] = flavor != "docker"
context["isNotK8s"] = flavor != "kubernetes"
context["isNotInstances"] = flavor != "instances"
context["isNotLite"] = flavor != "none"

context["hasContainers"] = context["isDocker"] or context["isK8s"]

# you can now actually remove items from the context
del context["flavor"]
```

Now you can use these added variables in your Jinja templates, and in files and folders
names!
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ nav:
- user_data.py: "reference/user_data.md"
- vcs.py: "reference/vcs.md"
- Comparisons: comparisons.md
- Frequently Asked Questions: faq.md
- Contributing: "contributing.md"
- Changelog: "changelog.md"

Expand Down