Search code examples
cookiecutter

cookie cutter: what's the easiest way to specify variables for the prompts


Is there anything that offers replay-type functionality, by pointing at a predefined prompt-answer file?

What works and what I'd like to achieve.

Let's take an example, using a cookiecutter to prep a Python package for pypi

cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git

You've downloaded /Users/jluc/.cookiecutters/cookiecutter-pypackage before. Is it okay to delete and re-download it? [yes]:
full_name [Audrey Roy Greenfeld]: Spartacus  👈 constant for me/my organization
email [[email protected]]: [email protected] 👈 constant for me/my organization
...
project_name [Python Boilerplate]: GladiatorRevolt 👈 this will vary.
project_slug [q]: gladiator-revolt 👈 this too
...

OK, done.

Now, I can easily redo this, for this project, via:

cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --replay

This is great!

What I want:

Say I create another project, UnleashHell.

I want to prep a file somehow that has my developer-info and project level info for Unleash. And I want to be able to run it multiple times against this template, without having to deal with prompts. This particular pypi template gets regular updates, for example python 2.7 support has been dropped.

The problem:

A --replay will just inject the last run for this cookiecutter template. If it was run against a different pypi project, too bad.

I'm good with my developer-level info, but I need to vary all the project level info.

I tried copying the replay file via:

cp ~/.cookiecutter_replay/cookiecutter-pypackage.json unleash.json

Edit unleash.json to reflect necessary changes.

Then specify it via --config-file flag

cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --config-file unleash.json

I get an ugly error, it wants YAML, apparently.

cookiecutter.exceptions.InvalidConfiguration: Unable to parse YAML file .../000.packaging/unleash.json. Error: None of the known patterns match for {
    "cookiecutter": {
        "full_name": "Spartacus",

No problem, json2yaml to the rescue.

That doesn't work either.

cookiecutter.exceptions.InvalidConfiguration: Unable to parse YAML file ./cookie.yaml. Error: Unable to determine type for "
    full_name: "Spartacus"

I also tried a < stdin redirect:

cookiecutter.prompts.txt:

yes
Spartacus
...

It doesn't seem to use it and just aborts.

cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git < ./cookiecutter.prompts.txt
You've downloaded ~/.cookiecutters/cookiecutter-pypackage before. Is it okay to delete and re-download it? [yes]
: full_name [Audrey Roy Greenfeld]
: email [[email protected]]
: Aborted

I suspect I am missing something obvious, not sure what. To start with, what is the intent and format expected for the --config file?

Debrief - how I got it working from accepted answer.

Took accepted answer, but adjusted it for ~/.cookiecutterrc usage. It works but the format is not super clear. Especially not on the rc which has to be yaml, though that's not always/often the case with rc files.

This ended up working:

file ~/.cookiecutterrc:

without nesting under default_context... tons of unhelpful yaml parse errors (on a valid yaml doc).

default_context:
    #... cut out for privacy
    add_pyup_badge: y
    command_line_interface: "Click"
    create_author_file: "y"
    open_source_license: "MIT license"

# the names to use here are:
    # full_name: 
    # email: 
    # github_username: 
    # project_name: 
    # project_slug: 
    # project_short_description: 
    # pypi_username: 
    # version: 
    # use_pytest: 
    # use_pypi_deployment_with_travis: 
    # add_pyup_badge: 
    # command_line_interface:
    # create_author_file: 
    # open_source_license:

I still could not get a combination of ~/.cookiecutterrc and a project-specific config.yaml to work. Too bad that expected configuration format is so lightly documented.

So I will use the .rc but enter the project name, slug and description each time. Oh well, good enough for now.


Solution

  • You are near.

    Try this cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --no-input --config-file config.yaml

    The --no-input parameter will suppress the terminal user input, it is optional of course.

    The config.yaml file could look like this:

    default_context:
        full_name: "Audrey Roy"
        email: "[email protected]"
        github_username: "audreyr"
    cookiecutters_dir: "/home/audreyr/my-custom-cookiecutters-dir/"
    replay_dir: "/home/audreyr/my-custom-replay-dir/"
    abbreviations:
        pp: https://github.com/audreyr/cookiecutter-pypackage.git
        gh: https://github.com/{0}.git
        bb: https://bitbucket.org/{0}
    

    Reference to this example file: https://cookiecutter.readthedocs.io/en/1.7.0/advanced/user_config.html

    You probably just need the default_context block since that is where the user input goes.