Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python cookiecutter loop over list

I am trying to loop over all items in a Python cookiecutter json list and run a bash command based on each item.

Setup

I have the following cookiecutter.json:

{
    "directory_name": "df-sharp",
    "servers": ["db", "web"],
    "myweb_provisioner": "webck"
}

I have {{cookiecutter.myweb_provisioner}}.sh, which contains this jinja2 code:

{% for server in cookiecutter.servers %}
mkdir -p ~/myproj/host_types/{{ server }}
{% endfor %}

Problem

When I run cookiecutter create-server-tree, I get the following:

Select servers:
1 - db
2 - web
Choose from 1, 2 [1]: 2

and the contents in webck.sh are:

mkdir -p ~/myproj/host_types/w
mkdir -p ~/myproj/host_types/e
mkdir -p ~/myproj/host_types/b

The Select menu should not appear. I do not want to choose between the 2 elements in the list. I want to loop over them and construct 2 bash commands - one command per element. I am trying to loop over the list like shown here or here.

What I want

This is what I want: cookiecutter create-server-tree should produce webck.sh which contains the following:

mkdir -p ~/myproj/host_types/db
mkdir -p ~/myproj/host_types/web

How can I iterate over the servers list and use each of the list elements (instead of one character at a time)?

like image 201
edesz Avatar asked Oct 29 '22 22:10

edesz


1 Answers

It turns out that I was using the wrong terminology. If the value in a key-value pair is a plain list, then cookiecutter calls that value (list) as providing "Multiple Choice options". So if I put in a plain list as the value for the key "servers", then I should expect to get the list of choices that I got above:

Select servers:
1 - db
2 - web
Choose from 1, 2 [1]: 2

What I needed was a nested dictionary as the value for the key servers, like they show here - it is called Dictionary Variables. To use this to answer my question, I changed my cookiecutter.json file to this:

{
    "directory_name": "df-sharp",
    "servers": {"server_list": ["db", "web"],
                "server_ips: ["123", "456"]"
               },
    "myweb_provisioner": "webck"
}

and then I used jinja2 as shown below:

{% for server in cookiecutter.servers.server_list %}
mkdir -p ~/myproj/host_types/{{ server }}
{% endfor %}

and this gave me what I wanted.

However, I had to use cookiecutter create-server-tree --no-input(link). This is because I have not been able to suppress only the prompt for a dictionary variable. I would have wanted this:

directory_name[df-sharp]: 
myweb_provisioner[webck]: 

and some way of specifying the key servers as a default argument. Actually, they have a default option here. It would be something like this and requires using their API:

cookiecutter('create-server-tree/',
             no_input=True,
             extra_context={"servers": {"server_list":['db','web'],
                                        "server_ips": ["123", "456"]
                                       }
                           }
            )

However, how should a user incorporate this extra_content={...} argument into an actual cookiecutter project and refer to "server_list" in jinja2 templated script? I don't know.

like image 73
edesz Avatar answered Nov 15 '22 14:11

edesz