copier icon indicating copy to clipboard operation
copier copied to clipboard

Documentation: Add dynamic choice generation and checking examples to mkdocs.

Open wolfiex opened this issue 10 months ago • 4 comments

Actual Situation

The ability to dynamically create choices is really useful and it should be given as an example in the documentation.

my_collection:
    type: str
    help: A collection of items
    choices: |
        {%- for my_item in items %}
        - {{my_item}}
        {%- endfor %}

And executed with

run_copy(copier_loc, out_dir, data = { "items": ['a','b','c'] } )

I am happy to add it to the mkdocs markdown, but am unsure where it would best live. Just following the Jinja/Macro templates subheading possibly? https://copier.readthedocs.io/en/stable/configuring/#importing-jinja-templates-and-macros

Desired Situation

More people are aware of the functionality.

Proposed solution

I add this to the documentation and it gets merged?

wolfiex avatar Apr 08 '25 16:04 wolfiex

I would propose a similar solution to passing through a function and performing a conditional check:

iac:
    type: str
    help: Which IaC tool do you use?
    choices:
        Terraform: tf
        Cloud Formation:
            value: cf
            validator: "{% if not check_installed(cloud) %}Requires AWS{% endif %}"

And run as:

def check_installed(x):
    ...

run_copy(copier_loc, out_dir, data = { "check_installed":check_installed } )

wolfiex avatar Apr 08 '25 16:04 wolfiex

Do you have an example where the choice items are not provided as runtime data? Or can you elaborate on your use case?

sisp avatar Apr 08 '25 16:04 sisp

Both methods work fine. It would be nice to have an example in the documentation demonstrating their use.

A use case would be polling an API to establish the latest selection of available choices, or having a function evaluate the possible choices based on a non-arbitary selection of items (e.g. currently running processes)

wolfiex avatar Apr 09 '25 11:04 wolfiex

Sorry for the long silence. 🫣 I've thought some more about the use case you've sketched, and while using data to inject choice items or functions works, it's a slight abuse of the original intent of this argument. Currently, anything in the data dict gets exposed in the Jinja render context, but a future version of Copier might enforce that only question keys are present in data.

I think it would be more idiomatic to use Jinja filters/tests for your sketched use cases:

  • my_collection:
        type: str
        help: A collection of items
        choices: |
            {%- for my_item in ('<uri>' | get_items) %}
            - {{my_item}}
            {%- endfor %}
    
  • iac:
        type: str
        help: Which IaC tool do you use?
        choices:
            Terraform: tf
            Cloud Formation:
                value: cf
                validator: "{% if cloud is not installed %}Requires AWS{% endif %}"
    

You can easily add custom filters/tests via a custom Jinja extension that can be part of the Copier template repository. For example, add a Jinja extension in extensions.py in the repo root and register it in copier.yml:

_jinja_extensions:
  - extensions.py:MyExtension

It's not the same use case, but I like referring to @pawamoy's copier-uv template that, e.g., registers a custom git_user_name filter to determine a user's name via Git.

WDYT?

sisp avatar Jun 20 '25 09:06 sisp