11

Is there a way to machine-generate some values, after the user has supplied some their values for the variables in cookiecutter.json?

The reason I ask is that:

  • one of the values I need to prompt for is rather hard for users to work out
  • but it's really easy for me to write some Python code to generate the right value

So I'd really like to be able to remove the user prompt, and calculate the value instead.

Things I've tried:

  • Searched online for an example pre_gen_project.py file to show how to do it
  • Read the cookiecutter Advanced Usage page

I'm using cookiecutter on the command line:

cookiecutter path_to_template

Am I missing any tricks?

Clare Macrae
  • 3,670
  • 2
  • 31
  • 45

2 Answers2

6

I needed this exact capability just a few days ago. The solution I came up with was to write a wrapper script for cookiecutter, similar to what is mentioned in:

http://cookiecutter.readthedocs.io/en/latest/advanced_usage.html#calling-cookiecutter-functions-from-python

My script generates a random string for use in a Django project. I called my script cut-cut:

#! /usr/bin/env python

from cookiecutter.main import cookiecutter

import os

rstring = ''.join([c for c in os.urandom(1024)
                   if c.isalnum()])[:64]

cookiecutter(
    'django-template',     # path/url to cookiecutter template
    extra_context={'secret': rstring},
)

So now I simply run cut-cut and step through the process as normal. The only difference is that the entry named secret in my cookiecutter.json file is prepopulated with the generated value in rstring from the script, provided via the extra_context passed.

You could modify the script to accept the template via the command line, but in my usage I always use the same template, thus I simply pass a hard coded value "django-template" as noted in the code above.

zzzirk
  • 1,582
  • 2
  • 14
  • 18
  • Thank you very much. Could you clarify one thing please: do users see a prompt for your 'secret' value - with rstring value in, that they have to accept - or have you found a way to put silently put a value in cookiecutter.json, without user prompt? – Clare Macrae Jun 06 '16 at 19:01
  • Yes, they still see the prompt WITH the rstring value as the default so they can accept it by simply pressing enter or they can type in whatever value they choose instead. It works exactly like the rest of the fields in cookiecutter. In addition, what you pass in the script is a dictionary you can actually provide defaults for multiple items as you choose. – zzzirk Jun 07 '16 at 12:34
  • Thanks. This is useful to add extra values before the user has supplied their input. This is a really nice idea... However, I'm actually looking for a way to provide values **after** the user has supplied input, based on their replies. – Clare Macrae Jun 07 '16 at 20:07
  • So are you looking for the secret prompt to behave differently based on earlier input? – zzzirk Jun 07 '16 at 22:24
  • So I think I may finally understand what you are getting at. Are you trying to skip input on some subset of fields that you want to somehow provide default values for? – zzzirk Jun 10 '16 at 01:13
  • Yes that's exactly right, and the challenge is that one of the default values is calculated by complex Python code, whose input is one of the other answers, and whose value users must never change. I've started to think that the only answer is to have two different cookiecutter sets, and have a hook in the first one calculate the derived values, then programmatically call the second one, disabling the prompt. I haven't been able to get my head around a sane folder structure, though. – Clare Macrae Jun 10 '16 at 04:34
  • Can you post the answer or link to the code. I am also looking for the same and I have no knowledge of Python. – Rahul Katariya Oct 08 '16 at 13:08
1

Let's say you need a new variable some_variable which equals to the cookiecutter.project_slug.replace('_', '-'). You also do not want to ask the user about this variable. That's why we need to refer it as _some_variable inside the cookiecutter.json

You can achieve this by following the further steps:

  1. Append "_some_variable": "" to the cookiecutter.json file
  2. Append into ./hooks/pre_gen_project.py the python logic which calculates the value for _some_variable, for example:
# set additional helper variables
{{ cookiecutter.update({"_some_variable": cookiecutter.project_slug.replace('_', '-')}) }}
  1. Now you can access this variable with updated value in your template files by:
"{{ cookiecutter._some_variable }}"

Credits to https://github.com/samj1912/cookiecutter-advanced-demo

zhukovgreen
  • 1,551
  • 16
  • 26