We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Boolean parameters parsed as String
* Cookiecutter version: 2.0
* Template project url: https://github.com/cookiecutter/cookiecutter-django
* Python version: 3.8
* Operating System: Linux

### Description:

We want to be able to ask the user for true/false questions.
The example template shows the current usage of boolean parameters, in {{cookiecutter.project_slug}}/.github/dependabot.yml:
`{%- if cookiecutter.use_docker == 'y' %}` 
This usage is rather problematic, as it is requires the user to enter exactly 'y'. If the user enters "yes" or "true" it won't be valid.

We want to add the ability to specify boolean parameters as "true" JSON booleans and naturally prompt for them.
Thus the usage of booleans in the template's cookiecutter.json would look like:
`"use_docker": false`
Instead of the current usage, which is:
 `"use_docker": "n"`

Currently this example boolean which is specified in the cookiecutter.json file is parsed as a string and thus checking for it would require a string comparison, which raises and exact same problem as the user would have to explicitly enter "true" or "false" instead of a boolean.

This would also simplify the usage of the boolean parameters in files, so the above shown dependabot.yml would change to:
`{%- if cookiecutter.use_docker %}` 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cookiecutter/prompt.py`
Content:
```
1 """Functions for prompting the user for project info."""
2 import functools
3 import json
4 from collections import OrderedDict
5 
6 import click
7 from jinja2.exceptions import UndefinedError
8 
9 from cookiecutter.environment import StrictEnvironment
10 from cookiecutter.exceptions import UndefinedVariableInTemplate
11 
12 
13 def read_user_variable(var_name, default_value):
14     """Prompt user for variable and return the entered value or given default.
15 
16     :param str var_name: Variable of the context to query the user
17     :param default_value: Value that will be returned if no input happens
18     """
19     # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt
20     return click.prompt(var_name, default=default_value)
21 
22 
23 def read_user_yes_no(question, default_value):
24     """Prompt the user to reply with 'yes' or 'no' (or equivalent values).
25 
26     Note:
27       Possible choices are 'true', '1', 'yes', 'y' or 'false', '0', 'no', 'n'
28 
29     :param str question: Question to the user
30     :param default_value: Value that will be returned if no input happens
31     """
32     # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt
33     return click.prompt(question, default=default_value, type=click.BOOL)
34 
35 
36 def read_repo_password(question):
37     """Prompt the user to enter a password.
38 
39     :param str question: Question to the user
40     """
41     # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt
42     return click.prompt(question, hide_input=True)
43 
44 
45 def read_user_choice(var_name, options):
46     """Prompt the user to choose from several options for the given variable.
47 
48     The first item will be returned if no input happens.
49 
50     :param str var_name: Variable as specified in the context
51     :param list options: Sequence of options that are available to select from
52     :return: Exactly one item of ``options`` that has been chosen by the user
53     """
54     # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt
55     if not isinstance(options, list):
56         raise TypeError
57 
58     if not options:
59         raise ValueError
60 
61     choice_map = OrderedDict((f'{i}', value) for i, value in enumerate(options, 1))
62     choices = choice_map.keys()
63     default = '1'
64 
65     choice_lines = ['{} - {}'.format(*c) for c in choice_map.items()]
66     prompt = '\n'.join(
67         (
68             f'Select {var_name}:',
69             '\n'.join(choice_lines),
70             'Choose from {}'.format(', '.join(choices)),
71         )
72     )
73 
74     user_choice = click.prompt(
75         prompt, type=click.Choice(choices), default=default, show_choices=False
76     )
77     return choice_map[user_choice]
78 
79 
80 DEFAULT_DISPLAY = 'default'
81 
82 
83 def process_json(user_value, default_value=None):
84     """Load user-supplied value as a JSON dict.
85 
86     :param str user_value: User-supplied value to load as a JSON dict
87     """
88     if user_value == DEFAULT_DISPLAY:
89         # Return the given default w/o any processing
90         return default_value
91 
92     try:
93         user_dict = json.loads(user_value, object_pairs_hook=OrderedDict)
94     except Exception:
95         # Leave it up to click to ask the user again
96         raise click.UsageError('Unable to decode to JSON.')
97 
98     if not isinstance(user_dict, dict):
99         # Leave it up to click to ask the user again
100         raise click.UsageError('Requires JSON dict.')
101 
102     return user_dict
103 
104 
105 def read_user_dict(var_name, default_value):
106     """Prompt the user to provide a dictionary of data.
107 
108     :param str var_name: Variable as specified in the context
109     :param default_value: Value that will be returned if no input is provided
110     :return: A Python dictionary to use in the context.
111     """
112     # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt
113     if not isinstance(default_value, dict):
114         raise TypeError
115 
116     user_value = click.prompt(
117         var_name,
118         default=DEFAULT_DISPLAY,
119         type=click.STRING,
120         value_proc=functools.partial(process_json, default_value=default_value),
121     )
122 
123     if click.__version__.startswith("7.") and user_value == DEFAULT_DISPLAY:
124         # click 7.x does not invoke value_proc on the default value.
125         return default_value  # pragma: no cover
126     return user_value
127 
128 
129 def render_variable(env, raw, cookiecutter_dict):
130     """Render the next variable to be displayed in the user prompt.
131 
132     Inside the prompting taken from the cookiecutter.json file, this renders
133     the next variable. For example, if a project_name is "Peanut Butter
134     Cookie", the repo_name could be be rendered with:
135 
136         `{{ cookiecutter.project_name.replace(" ", "_") }}`.
137 
138     This is then presented to the user as the default.
139 
140     :param Environment env: A Jinja2 Environment object.
141     :param raw: The next value to be prompted for by the user.
142     :param dict cookiecutter_dict: The current context as it's gradually
143         being populated with variables.
144     :return: The rendered value for the default variable.
145     """
146     if raw is None:
147         return None
148     elif isinstance(raw, dict):
149         return {
150             render_variable(env, k, cookiecutter_dict): render_variable(
151                 env, v, cookiecutter_dict
152             )
153             for k, v in raw.items()
154         }
155     elif isinstance(raw, list):
156         return [render_variable(env, v, cookiecutter_dict) for v in raw]
157     elif not isinstance(raw, str):
158         raw = str(raw)
159 
160     template = env.from_string(raw)
161 
162     rendered_template = template.render(cookiecutter=cookiecutter_dict)
163     return rendered_template
164 
165 
166 def prompt_choice_for_config(cookiecutter_dict, env, key, options, no_input):
167     """Prompt user with a set of options to choose from.
168 
169     :param no_input: Do not prompt for user input and return the first available option.
170     """
171     rendered_options = [render_variable(env, raw, cookiecutter_dict) for raw in options]
172     if no_input:
173         return rendered_options[0]
174     return read_user_choice(key, rendered_options)
175 
176 
177 def prompt_for_config(context, no_input=False):
178     """Prompt user to enter a new config.
179 
180     :param dict context: Source for field names and sample values.
181     :param no_input: Do not prompt for user input and use only values from context.
182     """
183     cookiecutter_dict = OrderedDict([])
184     env = StrictEnvironment(context=context)
185 
186     # First pass: Handle simple and raw variables, plus choices.
187     # These must be done first because the dictionaries keys and
188     # values might refer to them.
189     for key, raw in context['cookiecutter'].items():
190         if key.startswith('_') and not key.startswith('__'):
191             cookiecutter_dict[key] = raw
192             continue
193         elif key.startswith('__'):
194             cookiecutter_dict[key] = render_variable(env, raw, cookiecutter_dict)
195             continue
196 
197         try:
198             if isinstance(raw, list):
199                 # We are dealing with a choice variable
200                 val = prompt_choice_for_config(
201                     cookiecutter_dict, env, key, raw, no_input
202                 )
203                 cookiecutter_dict[key] = val
204             elif not isinstance(raw, dict):
205                 # We are dealing with a regular variable
206                 val = render_variable(env, raw, cookiecutter_dict)
207 
208                 if not no_input:
209                     val = read_user_variable(key, val)
210 
211                 cookiecutter_dict[key] = val
212         except UndefinedError as err:
213             msg = f"Unable to render variable '{key}'"
214             raise UndefinedVariableInTemplate(msg, err, context)
215 
216     # Second pass; handle the dictionaries.
217     for key, raw in context['cookiecutter'].items():
218         # Skip private type dicts not ot be rendered.
219         if key.startswith('_') and not key.startswith('__'):
220             continue
221 
222         try:
223             if isinstance(raw, dict):
224                 # We are dealing with a dict variable
225                 val = render_variable(env, raw, cookiecutter_dict)
226 
227                 if not no_input and not key.startswith('__'):
228                     val = read_user_dict(key, val)
229 
230                 cookiecutter_dict[key] = val
231         except UndefinedError as err:
232             msg = f"Unable to render variable '{key}'"
233             raise UndefinedVariableInTemplate(msg, err, context)
234 
235     return cookiecutter_dict
236
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cookiecutter/prompt.py b/cookiecutter/prompt.py
--- a/cookiecutter/prompt.py
+++ b/cookiecutter/prompt.py
@@ -143,8 +143,8 @@
         being populated with variables.
     :return: The rendered value for the default variable.
     """
-    if raw is None:
-        return None
+    if raw is None or isinstance(raw, bool):
+        return raw
     elif isinstance(raw, dict):
         return {
             render_variable(env, k, cookiecutter_dict): render_variable(
@@ -201,6 +201,14 @@
                     cookiecutter_dict, env, key, raw, no_input
                 )
                 cookiecutter_dict[key] = val
+            elif isinstance(raw, bool):
+                # We are dealing with a boolean variable
+                if no_input:
+                    cookiecutter_dict[key] = render_variable(
+                        env, raw, cookiecutter_dict
+                    )
+                else:
+                    cookiecutter_dict[key] = read_user_yes_no(key, raw)
             elif not isinstance(raw, dict):
                 # We are dealing with a regular variable
                 val = render_variable(env, raw, cookiecutter_dict)

{"golden_diff": "diff --git a/cookiecutter/prompt.py b/cookiecutter/prompt.py\n--- a/cookiecutter/prompt.py\n+++ b/cookiecutter/prompt.py\n@@ -143,8 +143,8 @@\n         being populated with variables.\n     :return: The rendered value for the default variable.\n     \"\"\"\n-    if raw is None:\n-        return None\n+    if raw is None or isinstance(raw, bool):\n+        return raw\n     elif isinstance(raw, dict):\n         return {\n             render_variable(env, k, cookiecutter_dict): render_variable(\n@@ -201,6 +201,14 @@\n                     cookiecutter_dict, env, key, raw, no_input\n                 )\n                 cookiecutter_dict[key] = val\n+            elif isinstance(raw, bool):\n+                # We are dealing with a boolean variable\n+                if no_input:\n+                    cookiecutter_dict[key] = render_variable(\n+                        env, raw, cookiecutter_dict\n+                    )\n+                else:\n+                    cookiecutter_dict[key] = read_user_yes_no(key, raw)\n             elif not isinstance(raw, dict):\n                 # We are dealing with a regular variable\n                 val = render_variable(env, raw, cookiecutter_dict)\n", "issue": "Boolean parameters parsed as String\n* Cookiecutter version: 2.0\r\n* Template project url: https://github.com/cookiecutter/cookiecutter-django\r\n* Python version: 3.8\r\n* Operating System: Linux\r\n\r\n### Description:\r\n\r\nWe want to be able to ask the user for true/false questions.\r\nThe example template shows the current usage of boolean parameters, in {{cookiecutter.project_slug}}/.github/dependabot.yml:\r\n`{%- if cookiecutter.use_docker == 'y' %}` \r\nThis usage is rather problematic, as it is requires the user to enter exactly 'y'. If the user enters \"yes\" or \"true\" it won't be valid.\r\n\r\nWe want to add the ability to specify boolean parameters as \"true\" JSON booleans and naturally prompt for them.\r\nThus the usage of booleans in the template's cookiecutter.json would look like:\r\n`\"use_docker\": false`\r\nInstead of the current usage, which is:\r\n `\"use_docker\": \"n\"`\r\n\r\nCurrently this example boolean which is specified in the cookiecutter.json file is parsed as a string and thus checking for it would require a string comparison, which raises and exact same problem as the user would have to explicitly enter \"true\" or \"false\" instead of a boolean.\r\n\r\nThis would also simplify the usage of the boolean parameters in files, so the above shown dependabot.yml would change to:\r\n`{%- if cookiecutter.use_docker %}` \n", "before_files": [{"content": "\"\"\"Functions for prompting the user for project info.\"\"\"\nimport functools\nimport json\nfrom collections import OrderedDict\n\nimport click\nfrom jinja2.exceptions import UndefinedError\n\nfrom cookiecutter.environment import StrictEnvironment\nfrom cookiecutter.exceptions import UndefinedVariableInTemplate\n\n\ndef read_user_variable(var_name, default_value):\n    \"\"\"Prompt user for variable and return the entered value or given default.\n\n    :param str var_name: Variable of the context to query the user\n    :param default_value: Value that will be returned if no input happens\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(var_name, default=default_value)\n\n\ndef read_user_yes_no(question, default_value):\n    \"\"\"Prompt the user to reply with 'yes' or 'no' (or equivalent values).\n\n    Note:\n      Possible choices are 'true', '1', 'yes', 'y' or 'false', '0', 'no', 'n'\n\n    :param str question: Question to the user\n    :param default_value: Value that will be returned if no input happens\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(question, default=default_value, type=click.BOOL)\n\n\ndef read_repo_password(question):\n    \"\"\"Prompt the user to enter a password.\n\n    :param str question: Question to the user\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(question, hide_input=True)\n\n\ndef read_user_choice(var_name, options):\n    \"\"\"Prompt the user to choose from several options for the given variable.\n\n    The first item will be returned if no input happens.\n\n    :param str var_name: Variable as specified in the context\n    :param list options: Sequence of options that are available to select from\n    :return: Exactly one item of ``options`` that has been chosen by the user\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    if not isinstance(options, list):\n        raise TypeError\n\n    if not options:\n        raise ValueError\n\n    choice_map = OrderedDict((f'{i}', value) for i, value in enumerate(options, 1))\n    choices = choice_map.keys()\n    default = '1'\n\n    choice_lines = ['{} - {}'.format(*c) for c in choice_map.items()]\n    prompt = '\\n'.join(\n        (\n            f'Select {var_name}:',\n            '\\n'.join(choice_lines),\n            'Choose from {}'.format(', '.join(choices)),\n        )\n    )\n\n    user_choice = click.prompt(\n        prompt, type=click.Choice(choices), default=default, show_choices=False\n    )\n    return choice_map[user_choice]\n\n\nDEFAULT_DISPLAY = 'default'\n\n\ndef process_json(user_value, default_value=None):\n    \"\"\"Load user-supplied value as a JSON dict.\n\n    :param str user_value: User-supplied value to load as a JSON dict\n    \"\"\"\n    if user_value == DEFAULT_DISPLAY:\n        # Return the given default w/o any processing\n        return default_value\n\n    try:\n        user_dict = json.loads(user_value, object_pairs_hook=OrderedDict)\n    except Exception:\n        # Leave it up to click to ask the user again\n        raise click.UsageError('Unable to decode to JSON.')\n\n    if not isinstance(user_dict, dict):\n        # Leave it up to click to ask the user again\n        raise click.UsageError('Requires JSON dict.')\n\n    return user_dict\n\n\ndef read_user_dict(var_name, default_value):\n    \"\"\"Prompt the user to provide a dictionary of data.\n\n    :param str var_name: Variable as specified in the context\n    :param default_value: Value that will be returned if no input is provided\n    :return: A Python dictionary to use in the context.\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    if not isinstance(default_value, dict):\n        raise TypeError\n\n    user_value = click.prompt(\n        var_name,\n        default=DEFAULT_DISPLAY,\n        type=click.STRING,\n        value_proc=functools.partial(process_json, default_value=default_value),\n    )\n\n    if click.__version__.startswith(\"7.\") and user_value == DEFAULT_DISPLAY:\n        # click 7.x does not invoke value_proc on the default value.\n        return default_value  # pragma: no cover\n    return user_value\n\n\ndef render_variable(env, raw, cookiecutter_dict):\n    \"\"\"Render the next variable to be displayed in the user prompt.\n\n    Inside the prompting taken from the cookiecutter.json file, this renders\n    the next variable. For example, if a project_name is \"Peanut Butter\n    Cookie\", the repo_name could be be rendered with:\n\n        `{{ cookiecutter.project_name.replace(\" \", \"_\") }}`.\n\n    This is then presented to the user as the default.\n\n    :param Environment env: A Jinja2 Environment object.\n    :param raw: The next value to be prompted for by the user.\n    :param dict cookiecutter_dict: The current context as it's gradually\n        being populated with variables.\n    :return: The rendered value for the default variable.\n    \"\"\"\n    if raw is None:\n        return None\n    elif isinstance(raw, dict):\n        return {\n            render_variable(env, k, cookiecutter_dict): render_variable(\n                env, v, cookiecutter_dict\n            )\n            for k, v in raw.items()\n        }\n    elif isinstance(raw, list):\n        return [render_variable(env, v, cookiecutter_dict) for v in raw]\n    elif not isinstance(raw, str):\n        raw = str(raw)\n\n    template = env.from_string(raw)\n\n    rendered_template = template.render(cookiecutter=cookiecutter_dict)\n    return rendered_template\n\n\ndef prompt_choice_for_config(cookiecutter_dict, env, key, options, no_input):\n    \"\"\"Prompt user with a set of options to choose from.\n\n    :param no_input: Do not prompt for user input and return the first available option.\n    \"\"\"\n    rendered_options = [render_variable(env, raw, cookiecutter_dict) for raw in options]\n    if no_input:\n        return rendered_options[0]\n    return read_user_choice(key, rendered_options)\n\n\ndef prompt_for_config(context, no_input=False):\n    \"\"\"Prompt user to enter a new config.\n\n    :param dict context: Source for field names and sample values.\n    :param no_input: Do not prompt for user input and use only values from context.\n    \"\"\"\n    cookiecutter_dict = OrderedDict([])\n    env = StrictEnvironment(context=context)\n\n    # First pass: Handle simple and raw variables, plus choices.\n    # These must be done first because the dictionaries keys and\n    # values might refer to them.\n    for key, raw in context['cookiecutter'].items():\n        if key.startswith('_') and not key.startswith('__'):\n            cookiecutter_dict[key] = raw\n            continue\n        elif key.startswith('__'):\n            cookiecutter_dict[key] = render_variable(env, raw, cookiecutter_dict)\n            continue\n\n        try:\n            if isinstance(raw, list):\n                # We are dealing with a choice variable\n                val = prompt_choice_for_config(\n                    cookiecutter_dict, env, key, raw, no_input\n                )\n                cookiecutter_dict[key] = val\n            elif not isinstance(raw, dict):\n                # We are dealing with a regular variable\n                val = render_variable(env, raw, cookiecutter_dict)\n\n                if not no_input:\n                    val = read_user_variable(key, val)\n\n                cookiecutter_dict[key] = val\n        except UndefinedError as err:\n            msg = f\"Unable to render variable '{key}'\"\n            raise UndefinedVariableInTemplate(msg, err, context)\n\n    # Second pass; handle the dictionaries.\n    for key, raw in context['cookiecutter'].items():\n        # Skip private type dicts not ot be rendered.\n        if key.startswith('_') and not key.startswith('__'):\n            continue\n\n        try:\n            if isinstance(raw, dict):\n                # We are dealing with a dict variable\n                val = render_variable(env, raw, cookiecutter_dict)\n\n                if not no_input and not key.startswith('__'):\n                    val = read_user_dict(key, val)\n\n                cookiecutter_dict[key] = val\n        except UndefinedError as err:\n            msg = f\"Unable to render variable '{key}'\"\n            raise UndefinedVariableInTemplate(msg, err, context)\n\n    return cookiecutter_dict\n", "path": "cookiecutter/prompt.py"}], "after_files": [{"content": "\"\"\"Functions for prompting the user for project info.\"\"\"\nimport functools\nimport json\nfrom collections import OrderedDict\n\nimport click\nfrom jinja2.exceptions import UndefinedError\n\nfrom cookiecutter.environment import StrictEnvironment\nfrom cookiecutter.exceptions import UndefinedVariableInTemplate\n\n\ndef read_user_variable(var_name, default_value):\n    \"\"\"Prompt user for variable and return the entered value or given default.\n\n    :param str var_name: Variable of the context to query the user\n    :param default_value: Value that will be returned if no input happens\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(var_name, default=default_value)\n\n\ndef read_user_yes_no(question, default_value):\n    \"\"\"Prompt the user to reply with 'yes' or 'no' (or equivalent values).\n\n    Note:\n      Possible choices are 'true', '1', 'yes', 'y' or 'false', '0', 'no', 'n'\n\n    :param str question: Question to the user\n    :param default_value: Value that will be returned if no input happens\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(question, default=default_value, type=click.BOOL)\n\n\ndef read_repo_password(question):\n    \"\"\"Prompt the user to enter a password.\n\n    :param str question: Question to the user\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    return click.prompt(question, hide_input=True)\n\n\ndef read_user_choice(var_name, options):\n    \"\"\"Prompt the user to choose from several options for the given variable.\n\n    The first item will be returned if no input happens.\n\n    :param str var_name: Variable as specified in the context\n    :param list options: Sequence of options that are available to select from\n    :return: Exactly one item of ``options`` that has been chosen by the user\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    if not isinstance(options, list):\n        raise TypeError\n\n    if not options:\n        raise ValueError\n\n    choice_map = OrderedDict((f'{i}', value) for i, value in enumerate(options, 1))\n    choices = choice_map.keys()\n    default = '1'\n\n    choice_lines = ['{} - {}'.format(*c) for c in choice_map.items()]\n    prompt = '\\n'.join(\n        (\n            f'Select {var_name}:',\n            '\\n'.join(choice_lines),\n            'Choose from {}'.format(', '.join(choices)),\n        )\n    )\n\n    user_choice = click.prompt(\n        prompt, type=click.Choice(choices), default=default, show_choices=False\n    )\n    return choice_map[user_choice]\n\n\nDEFAULT_DISPLAY = 'default'\n\n\ndef process_json(user_value, default_value=None):\n    \"\"\"Load user-supplied value as a JSON dict.\n\n    :param str user_value: User-supplied value to load as a JSON dict\n    \"\"\"\n    if user_value == DEFAULT_DISPLAY:\n        # Return the given default w/o any processing\n        return default_value\n\n    try:\n        user_dict = json.loads(user_value, object_pairs_hook=OrderedDict)\n    except Exception:\n        # Leave it up to click to ask the user again\n        raise click.UsageError('Unable to decode to JSON.')\n\n    if not isinstance(user_dict, dict):\n        # Leave it up to click to ask the user again\n        raise click.UsageError('Requires JSON dict.')\n\n    return user_dict\n\n\ndef read_user_dict(var_name, default_value):\n    \"\"\"Prompt the user to provide a dictionary of data.\n\n    :param str var_name: Variable as specified in the context\n    :param default_value: Value that will be returned if no input is provided\n    :return: A Python dictionary to use in the context.\n    \"\"\"\n    # Please see https://click.palletsprojects.com/en/7.x/api/#click.prompt\n    if not isinstance(default_value, dict):\n        raise TypeError\n\n    user_value = click.prompt(\n        var_name,\n        default=DEFAULT_DISPLAY,\n        type=click.STRING,\n        value_proc=functools.partial(process_json, default_value=default_value),\n    )\n\n    if click.__version__.startswith(\"7.\") and user_value == DEFAULT_DISPLAY:\n        # click 7.x does not invoke value_proc on the default value.\n        return default_value  # pragma: no cover\n    return user_value\n\n\ndef render_variable(env, raw, cookiecutter_dict):\n    \"\"\"Render the next variable to be displayed in the user prompt.\n\n    Inside the prompting taken from the cookiecutter.json file, this renders\n    the next variable. For example, if a project_name is \"Peanut Butter\n    Cookie\", the repo_name could be be rendered with:\n\n        `{{ cookiecutter.project_name.replace(\" \", \"_\") }}`.\n\n    This is then presented to the user as the default.\n\n    :param Environment env: A Jinja2 Environment object.\n    :param raw: The next value to be prompted for by the user.\n    :param dict cookiecutter_dict: The current context as it's gradually\n        being populated with variables.\n    :return: The rendered value for the default variable.\n    \"\"\"\n    if raw is None or isinstance(raw, bool):\n        return raw\n    elif isinstance(raw, dict):\n        return {\n            render_variable(env, k, cookiecutter_dict): render_variable(\n                env, v, cookiecutter_dict\n            )\n            for k, v in raw.items()\n        }\n    elif isinstance(raw, list):\n        return [render_variable(env, v, cookiecutter_dict) for v in raw]\n    elif not isinstance(raw, str):\n        raw = str(raw)\n\n    template = env.from_string(raw)\n\n    rendered_template = template.render(cookiecutter=cookiecutter_dict)\n    return rendered_template\n\n\ndef prompt_choice_for_config(cookiecutter_dict, env, key, options, no_input):\n    \"\"\"Prompt user with a set of options to choose from.\n\n    :param no_input: Do not prompt for user input and return the first available option.\n    \"\"\"\n    rendered_options = [render_variable(env, raw, cookiecutter_dict) for raw in options]\n    if no_input:\n        return rendered_options[0]\n    return read_user_choice(key, rendered_options)\n\n\ndef prompt_for_config(context, no_input=False):\n    \"\"\"Prompt user to enter a new config.\n\n    :param dict context: Source for field names and sample values.\n    :param no_input: Do not prompt for user input and use only values from context.\n    \"\"\"\n    cookiecutter_dict = OrderedDict([])\n    env = StrictEnvironment(context=context)\n\n    # First pass: Handle simple and raw variables, plus choices.\n    # These must be done first because the dictionaries keys and\n    # values might refer to them.\n    for key, raw in context['cookiecutter'].items():\n        if key.startswith('_') and not key.startswith('__'):\n            cookiecutter_dict[key] = raw\n            continue\n        elif key.startswith('__'):\n            cookiecutter_dict[key] = render_variable(env, raw, cookiecutter_dict)\n            continue\n\n        try:\n            if isinstance(raw, list):\n                # We are dealing with a choice variable\n                val = prompt_choice_for_config(\n                    cookiecutter_dict, env, key, raw, no_input\n                )\n                cookiecutter_dict[key] = val\n            elif isinstance(raw, bool):\n                # We are dealing with a boolean variable\n                if no_input:\n                    cookiecutter_dict[key] = render_variable(\n                        env, raw, cookiecutter_dict\n                    )\n                else:\n                    cookiecutter_dict[key] = read_user_yes_no(key, raw)\n            elif not isinstance(raw, dict):\n                # We are dealing with a regular variable\n                val = render_variable(env, raw, cookiecutter_dict)\n\n                if not no_input:\n                    val = read_user_variable(key, val)\n\n                cookiecutter_dict[key] = val\n        except UndefinedError as err:\n            msg = f\"Unable to render variable '{key}'\"\n            raise UndefinedVariableInTemplate(msg, err, context)\n\n    # Second pass; handle the dictionaries.\n    for key, raw in context['cookiecutter'].items():\n        # Skip private type dicts not ot be rendered.\n        if key.startswith('_') and not key.startswith('__'):\n            continue\n\n        try:\n            if isinstance(raw, dict):\n                # We are dealing with a dict variable\n                val = render_variable(env, raw, cookiecutter_dict)\n\n                if not no_input and not key.startswith('__'):\n                    val = read_user_dict(key, val)\n\n                cookiecutter_dict[key] = val\n        except UndefinedError as err:\n            msg = f\"Unable to render variable '{key}'\"\n            raise UndefinedVariableInTemplate(msg, err, context)\n\n    return cookiecutter_dict\n", "path": "cookiecutter/prompt.py"}]}