emrec
emrec

Reputation: 75

How to use dynamic variables in cookiecutter hooks?

I would like to use dynamic variables inside hooks/pre_gen_project.py.

When I add a static text inside the hook file it works:

{{ cookiecutter.update({"venv_path": "static/venvpath", "py_path": "static/pypath"}) }}

But when I tried to use a variable like venv_path_val

venv_path_val = "static/venvpath"
py_path_val = "static/pypath"
{{ cookiecutter.update({"venv_path": venv_path_val, "py_path": py_path_val }) }}

I am getting

jinja2.exceptions.UndefinedError: 'venv_path_val' is undefined

I also tried it inside eval but no luck:

eval("{{ '{{'|safe }} cookiecutter.update({'venv_path': venv_path, 'py_path': py_path}) {{ '}}'|safe }}")

So is there a way to inject my dynamic template variables inside cookiecutter?

Upvotes: 7

Views: 2035

Answers (2)

Mike McKay
Mike McKay

Reputation: 2656

I was also stuck on this for a few days. Eventually, I decided that my solution would be to try and open the cookiecutter configuration file from a pre_prompt hook instead of pre_gen_project. Then I could just insert my dynamically genereated data into a .cookiecutterrc file, which would then be used as default values by cookie cutter. However, the answer turned out to be a lot simpler than that. You can open the cookiecutter.json, update the values with your dynamic data, and then write it. Apparently this process is working on a cookiecutter.json file in a tmp directory, not the original, so the original doesn't get changed, but the dynamic values do show up in the prompts and the resulting templates. Here's an example snippet for hooks/pre_prompt.py

import os
import pwd
from pathlib import Path
                   
config = Path("cookiecutter.json")
data = json.loads(config.read_text())
                   
data["name"] = pwd.getpwuid(os.geteuid())[4].split(",")[0] # Get name of current user
data["technology"] = os.getenv("CURRENT_TECHNOLOGY") # Read an environment variable
                   
config.write_text(json.dumps(data, indent=4))

Upvotes: 1

Stefan
Stefan

Reputation: 59

I haven't figured this out either. An alternative to this would be to inject extra context

In your case, add the following to your hooks/pre_gen_project.py

from cookiecutter.main import cookie-cutter

venv_path = "static/venvpath"
py_path = "static/pypath"

cookiecutter(
    'cookiecutter-django',
    extra_context={
        'venv_path': venv_path,
        'py_path': py_path
    })
)

Upvotes: 2

Related Questions