Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

passing list to template #479

Closed
bsdlp opened this issue Jul 29, 2015 · 4 comments
Closed

passing list to template #479

bsdlp opened this issue Jul 29, 2015 · 4 comments

Comments

@bsdlp
Copy link

bsdlp commented Jul 29, 2015

I would like to be able to pass a list to the templates. See the two code blocks at the end of this post for an example. Right now it appears that if you pass a list in the config object, it's read as a list of options for that key.

I know that you can use str.split() in the jinja2 template, but that's not a real solution, since it's impossible to "escape" the character that's used as the delimiter. What's the best solution here? I would prefer to be able to pass a list in the json object and call it a day, but obviously that doesn't work for the user input prompts.

  • cookiecutter.json:
{
  "build_steps": [
     "do_something",
     "do_something_else"
  ]
}
  • Dockerfile:
FROM something

{% for step in cookiecutter.build_steps %}
RUN {{ step }}
{% endfor %}
@hackebrot
Copy link
Member

Hi @fly, thank you for submitting an issue 🙇

I guess we need to rework the context config in order to support complex values and type checks. Currently lists are treated as options.

@freakboy3742
Copy link
Contributor

@hackebrot This is something I have a need for as well, and I might be motivated enough to look into implementing it (as I need this to support exported data types Briefcase). Has any thought been given to a preferred way to handle this?

The easiest option I can think of: Since JSON lists are already being used as "choices", we could modify the interpretation of dictionaries to always be "deep" data structures, and then use a structure like:

"key": {
    "values": [1,2,3,4]
}

if you need a list. Yes, this introduces an extra layer into the data structure exposed to the template, but the way choices are handled has already painted this situation into a corner. I suppose this case could be handled with a special case in the data structure - e.g., if your dictionary has a single key called "list", the value is interpreted as a literal list, rather than a dictionary containing that list. However, this would be a bit of a magical hack IMHO.

Regardless of whether the "list reduction hack" is used, the UI for dictionary handling could be supplemented by JSON parsing for the command line interface; If the cookiecutter.json specifies a dictionary as the default (even an empty dictionary), then the command line UI could parse the content as JSON, rather than treating it as a literal string.

An alternative option that would work for my use case, but probably not for the general case, would be a flag to the API for cookiecutter that ensures that extra_context is passed through as literals (possibly only when no_input=True is passed in as well - so you can opt for a literal, pre-parsed interpretation of extra_context).

Do any of these options sound appealing?

@bukowa
Copy link

bukowa commented Aug 5, 2020

Still not accepting a list of values?

@wulmer
Copy link

wulmer commented May 17, 2021

We have had the same problem recently and solved it by moving the list into a dictionary (as proposed in #479).
So, @bukowa, passing lists as arguments is possible, but only if the list is nested in a dictionary.

I did a quick test and the following template and input files demonstrate the problem quite well (but remember: it's not a but, it's a feature, see choice variables):

# File: {{cookiecutter.project_slug}}/test.py
print('{{ cookiecutter.string }}')
print('{{ cookiecutter.list }}')
print("{{ cookiecutter.dict }}")
// File cookiecutter.json
{
    "project_slug": "myproject",
    "string": "a string",
    "list": ["a", "list", "of", "items"],
    "dict": {"nested_list": ["a", "b", "c"]}
}

Which gives as result (when run with --no-input):

# File myproject/test.py
print('a string')
print('a')
print("{'nested_list': ['a', 'b', 'c']}")

If you run without --no-input, the cookiecutter template wizard asks you which option you want to select for the list entry and proposes "a" as default. That's the reason why the {{ cookiecutter.list }} entry only contains one item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants