My Cookiecutter project is structured like this
├── project
│ ├── {{Cookiecutter.client_name}}
│ │ ├── {{Cookiecutter.account_name}}
│ │ │ │── some-folder
│ │ │ ├── {{Cookiecutter.account_name}}.py
cookiecutter.json
looks like this
{
"client_name": "client",
"account_name": "account"
}
Now, in place of one account_name
. I want to add multiple account_names so that when Cookiecutter generates the project {{Cookiecutter.client_name}}
should have multiple folders like account1, account2, account3 and so on..
I have went through the Cookiecutter docs couldn't find anything meaningful or on how to go about it.
AFAIK this is not possible with cookiecutter if the number of accounts is not fixed in advance. But you can achieve the same effect with a hook. Something like this: (n.b. untested)
├── project
│ ├── {{ client_name }}
│ │ ├── account_name
│ │ │ │── some-folder
│ │ │ ├── account_name.py
| |-- hooks
| | |-- post_gen_project.py
# post_gen_project.py
# runs from the *generated* project
from pathlib import Path
from shutil import copy, rmtree
accounts = [x.strip() for x in {{ accounts }}.split(",")] # cookiecutter will render this for you
client_name = {{ client_name }}
src = Path(client_name)
for account in accounts:
copy(src / "account_name", src/account)
fn = src/ f"account/account_name.py"
fn.rename(fn.with_name(f"{account}.py"))
rmtree(src)
If you have lots of this to do, you might be better off just writing a deploy script yourself and avoiding cookiecutter.
I am assuming that your accounts are entered ,
separated: I can't remember if there's any way to get a raw list type in cookiecutter.
Yet another option is to use nested cookiecutters---specifically, calling a cookiecutter for account
from the post_gen hook, in a loop until the user no longer wants to add accounts. Something like this (again untested, provided as a starting point):
├── project
│ ├── {{ client_name }}
│ │ ├── account_template
| | | |-- {{ account_name }}
│ | │ │ │── some-folder
│ | │ │ ├── {{ account_name }}.py
| |-- hooks
| | |-- post_gen_project.py
# cookiecutter_project.json
...
"_copy_without_render": ["account_template/"]
This gets our inner cookiecutter deployed where we want it without rendering it. Then in the inner cookiecutter:
# account_template/cookiecutter.json
{ "account_name": "default account", "client_name": "default client"}
And then finally, in the outer cookiecutter's hook:
# hooks/post_gen_project.py
from shutil import rmtree
from cookiecutter.main import cookiecutter
client_name = {{ client_name }}
cont = True
while cont:
account_name = input("Enter account name: ")
cookiecutter(
"template_account",
no_input=True,
extra_content=dict(
account_name=account_name,
client_name=client_name
)
)
cont = not input("Press enter to continue").strip()
rmtree("template_account")
If the number of accounts is fixed in advance it's easy---just name one set account1
, the next account2
and so on.
References:
https://cookiecutter.readthedocs.io/en/1.7.3/advanced/hooks.html https://cookiecutter.readthedocs.io/en/1.7.3/advanced/suppressing_prompts.html#suppressing-command-line-prompts