Replies: 2 comments 7 replies
-
I just made #1205 without seeing this. |
Beta Was this translation helpful? Give feedback.
-
Hi everybody! Thanks for this thread, I think this is really needed. This feature is asked so often that I'm losing more time and energy explaining why this isn't supported than the time I'd lose supporting it. To clarify the problem, using Now, regarding the solution you're proposing here @sisp, I can tell you that this is something that came to my mind in the past. However, this solution would be rather complex to implement, dealing with what is vs what is not lazy. At the end of the day, believe me: the next day you pushed this feature, some issue would appear because somebody hits https://github.com/orgs/copier-org/discussions/1203#discussioncomment-6221750. At the end of the day, the main reason why we never supported Lines 144 to 147 in c16b0b8 So, now that we don't record skipped answers, I think that the ultimate solution is what I said in #1206 (comment). This solution:
However, it doesn't solve the case explained here by @sisp: the fact of being able to pass in a python function. However, think about it. If we added support for that, we'd be introducing yet another unsafe path into a template. At the end of the day, if you need a version validator in context, that's better handled by a jinja extension, just like it happened with jsonschema not so long ago (and you created https://github.com/copier-org/jinja2-jsonschema which is great!). That is already an unsafe feature, but it's completely supported right now. Also, remember (yes, I'm hammering with this, but this is really true!) that jinja supports a lot of features: macro, import, set, namespace... If you ever need a more complex type for your template, you have those features at hand. At the end of the day, the only thing this feature adds is ergonomy. You can achieve anything today with just jinja. Put in other terms: if we had this supported, would we need the more complex approach you propose here @sisp? IMHO probably not. So, my proposal is that we just go forward with the MVP at #1206 (comment) and continue our happy lives. |
Beta Was this translation helpful? Give feedback.
-
Background
Creating internal/private/computed/derived variables (typically) from answers of the questionnaire is a recurring topic and request (#229, #545, #629, #678 (comment), #700, #716, #1195 (comment)) which is partially solved by Jinja import/include (see test cases for some inspiration), but this approach is slightly unintuitive and can only derive string variables. Alternatively, the context hook extension can be used, but it requires installing the
copier-templates-extensions
package which makes a Copier template unsafe (for good reason because arbitrary code can be executed) even when no other Jinja extensions, migrations or tasks are used.I think I've come up with a more idiomatic solution to this problem.
Solution idea
We could add a new setting to the
copier.yml
file, e.g._jinja_extra_context
, where derived variables are defined:Then, we could extend the current render context by a new field, e.g.
_copier_extra
, whose value is aMapping
with a custom implementation of the__getitem__
method which renders the template of the requested derived variable. Here is a minimal and isolated example of the setup:Native types
In addition, it would be possible to extend this approach to support derived non-string variables through Jinja native types (although this has some limitations), e.g. by allowing a custom YAML tag like
!!jinja-native
to inform Copier that those derived variables shall be rendered using a native environment:Additional context
I originally tried to avoid a new context key like
_copier_extra
and "magically" add (lazily evaluated) derived variables to the root context, and for this I experimented withlazy-object-proxy
, but it doesn't work because Jinja does a shallow copy of the provided context in therender()
method call which triggers the evaluation of the proxied object. This leads to eager evaluation of all derived variables which isn't possible when using derived variables in the middle of the questionnaire where some (actually unused) derived variables depend on answers to questions which haven't been answered yet.Beta Was this translation helpful? Give feedback.
All reactions