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

Allow imports in inline templates #718

Closed
yajo opened this issue Jul 16, 2022 · 0 comments · Fixed by #986
Closed

Allow imports in inline templates #718

yajo opened this issue Jul 16, 2022 · 0 comments · Fixed by #986
Labels
enhancement help wanted The issue is valid, but we need community contributions to fix it
Milestone

Comments

@yajo
Copy link
Member

yajo commented Jul 16, 2022

Is your feature request related to a problem? Please describe.

Copier users keep requesting variables support. There are good reasons to avoid supporting variables:

However, it's easy to understand that people still need to keep their templates DRY.

The real problem is not within the template files. As said, Jinja is DRY enough out of the box. The real problem lies within 2 other spaces:

  1. Inside copier.yaml. Here, keys are not rendered but values are.
  2. Templated file and directory names.

These are not files, so they get rendered in-line:

template = self.jinja_env.from_string(value)

Describe the solution you'd like

I really don't want to create a new system for declaring variables or importing code when Jinja already has them. I just want to be able to use them in in-line templates.

This way, I could declare a copier.yaml like this:

_exclude:
  - name-slug

name:
  type: str
  default: A nice human-readable name

slug:
  type: str
  default: '{% include "name-slug.jinja" %}'

Also, I could have a template structure like this:

📄 copier.yaml
📄 name-slug.jinja
🐍  {% include "name-slug.jinja" %}.py

Apart from freeing Copier devs from reinventing some wheels, this would empower Copier templaters to not only add variables, but rather do a lot more stuff. Also it would make them more used to get reusable knowledge on the Jinja engine, rather than on a niche use case such as Copier.

Describe how to implement it

Quoting from Jinja docs:

Using a template loader rather than passing strings to Template or Environment.from_string() has multiple advantages. Besides being a lot easier to use it also enables template inheritance.

In other words, you can't import or include from an in-line template (or without a loader).

However, in our in-line templates, we do have a filesystem location context. So, the solution is relatively simple:

  1. Write a custom loader that tells Jinja that context.
  2. Let Copier know which loader to use, depending on where the rendered value comes from (is it a file? a path? or a copier.yml value?). This would mean possibly using one of PrefixLoader or ChoiceLoader.

Describe alternatives you've considered

See other user requests. All of them contain workarounds:

Additional context

Cookiecutter has private variables.

@yajo yajo added enhancement help wanted The issue is valid, but we need community contributions to fix it labels Jul 16, 2022
@yajo yajo added this to the Next milestone Jul 16, 2022
@yajo yajo mentioned this issue Jul 16, 2022
@yajo yajo closed this as completed in #986 Apr 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement help wanted The issue is valid, but we need community contributions to fix it
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant