copier-org / copier

Library and command-line utility for rendering projects templates.
https://readthedocs.org/projects/copier/
MIT License
1.99k stars 178 forks source link

Before rendering a file, add `_template_file` and `_this_file` to the context #1453

Open bswck opened 10 months ago

bswck commented 10 months ago

Actual Situation

During developing my template, I've decided that it would be a good idea to place comments a'la "this file was created from template, consider changing the template" in files that come from the template:

https://github.com/bswck/downstream/blob/c28c694f011aab17a6f7185d948bddd4a5657309/.gitignore#L1-L3

But I had to use this ugly hardcoding the relpath:

https://github.com/bswck/skeleton/blob/35fb54c5ce37f28201eea2f532570192449d61f4/project/.gitignore.jinja#L1C5-L1C31

Same for other template-managed files.

Desired Situation

I can consistently use {{_template_file|skeleton_notice(snref=snref, srev=srev)|line_prefix("# ")}} in every file. This will prevent any future situations where I rename a template file, but the skeleton notice remains unchanged with the broken path.

Proposed solution

Before rendering a file, add _template_file and _this_file to the context (naming can be different). I suggest _this_file apart from _template_file for consistency.

I can take this task if you would like this to be implemented.

yajo commented 10 months ago

I don't see how a comment in the file telling the name of the file would be useful, but I also have nothing against the feature if someone wants to contribute it.

bswck commented 10 months ago

I don't see how a comment in the file telling the name of the file would be useful

Telling the template filename would be useful in comments, because it can navigate template downstream projects contributors to change things in templates -- at the infrastructure level -- not in the downstream files.

When it comes to exposing filenames of the rendered files to themselves, I think it can potentially be useful to, for example, pass those filenames to filters from the template extensions that could customize behavior, such as automatically documenting in the README which files come from the copier template and which not. Just as an example.

bswck commented 10 months ago

I think it is technically possible to retrieve these metadata from Jinja2 itself as it renders files, but it isn't quite convenient programmatically, because it has no real use in website HTML templates Jinja2 is primarily designed for.

yajo commented 10 months ago

Have you tried this? https://stackoverflow.com/a/40346872/1468388

bswck commented 10 months ago

Have you tried this? stackoverflow.com/a/40346872/1468388

This is what I was referring to. But instead, I've built an extension that sets _origin in my context. Anyway, I still think setting these variables might be useful universally.

bswck commented 10 months ago

Especially since in the raw template filename there is this /tmp/<some_copier_unique_dir>/ prefix, which could ideally be stripped.

yajo commented 10 months ago

OK makes sense.

Add _copier prefix to the variables, as we usually do. Example: _copier_src_file and _copier_dst_file

ssteinerx commented 9 months ago

I would also find it useful to access the template file name and the eventual output file name.

It's especially useful in scenarios like YAML Front Matter for markdown files, which are part of documentation or static site generators like Jekyll.

Regarding the code snipped in the shared Stack Overflow link, when I try it I get this:

  {{ self._TemplateReference__context.name }}

Raises:

jinja2.exceptions.SecurityError: access to attribute '_TemplateReference__context' of 'TemplateReference' object is unsafe.

I've looked at the extensions/context.py and am poking around, but it would be very helpful not to have to take a deep dive into extensions and context management to access basic context information like the current template (or the list of inherited templates!) and output file name.

mike-lev-c commented 3 months ago

For reference I am considering overriding the entire run_copy method in a subclass and avoid the cli entirely because of the very opinionated render_paths method in worker. Aside from just simple references to print as comments... the unknown context becomes an issue when trying to render an application directory template that may have a variable number of submodules (ie a template for MVC pattern with multiple routes) based on a users input. I would like to venture out and propose an idea of separating the path rendering and the content rendering - my initial approach would be to use some sort of base xml template to achieve this