Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a coockiecutter template, add folder only if choice variable has a given value

I am creating a cookiecutter template and would like to add a folder (and the files it contains) only if a variable has a given value. For example cookiecutter.json:

{
    "project_slug":"project_folder"
    "i_want_this_folder":['y','n']
}

and my template structure looks like:

template
└── {{ cookiecutter.project_slug }}
    ├── config.ini
    ├── data
    │   └── data.csv
    ├── {% if cookiecutter.i_want_this_folder == 'y' %}my_folder{% endif %}
        └── some_files

However, when running cookiecutter template and choose 'n' I get an error

Error: "~/project_folder" directory already exists

Is my syntax for the folder name correct?

like image 659
Oneira Avatar asked Nov 07 '22 04:11

Oneira


1 Answers

I was facing the same issue having the option to add or no folders with different contents (all folders can exist at the same time). The structure of the project is the following:

├── {{cookiecutter.project_slug}}                 
│   │
│   ├── folder_1_to_add_or_no 
│   │    ├── file1.py
│   │    ├── file2.py
│   │    └── file3.txt
│   │
│   ├── folder_2_to_add_or_no 
│   │    ├── image.png
│   │    ├── data.csv
│   │    └── file.txt         
│   │
│   └── folder_3_to_add_or_no 
│        ├── file1.py
│        └── some_dir 
│
├── hooks 
│   └── post_gen_project.py 
│
└── cookiecutter.json 

where the cookiecutter.json contains the following

{
  "project_owner": "some-name",
  "project_slug": "some-project",
  "add_folder_one": ["yes", "no"],
  "add_folder_two": ["yes", "no"],
  "add_folder_three": ["yes", "no"],
}

as each directory folder_X_to_add_or_no contains different files, the trick is to remove those folders that the answer is "no", you can do this through a hook. Inside the post_gen_project.py file

# post_gen_project.py
import os
import shutil

from pathlib import Path

# Current path
path = Path(os.getcwd())

# Source path
parent_path = path.parent.absolute()

def remove(filepath):
    if os.path.isfile(filepath):
        os.remove(filepath)
    elif os.path.isdir(filepath):
        shutil.rmtree(filepath)
        
folders_to_add = [
    'folder_one',
    'folder_two',
    'folder_three'
] 

for folder in folders_to_add:

    # Check if user wants the folder
    cookiecutter_var = '{{cookiecutter.' + f'{folder}' + '}}'
    add_folder = cookiecutter_var == 'yes'
    
    # User does not want folder so remove it
    if not add_folder:

        folder_path = os.path.join(
            parent_path, 
            '{{cookiecutter.project_slug}}', 
            'folder'
        )

        remove(folder_path)

Now the folders the user choose not to add will be removed.

Select add_folder_one:
1 - yes
2 - no
Choose from 1, 2 [1]: 

References

This answer is based on briancapello answer on this github issue

like image 196
Miguel Trejo Avatar answered Dec 10 '22 16:12

Miguel Trejo