0
# User Interaction
1
2
Interactive prompts for template variables with support for different input types including text, choices, boolean, and JSON inputs. This module handles all user interaction during the template generation process.
3
4
## Capabilities
5
6
### Main Prompt Functions
7
8
Core prompting functionality for gathering user input during template generation.
9
10
```python { .api }
11
def prompt_for_config(context, no_input=False):
12
"""
13
Main function to prompt user for project config.
14
15
Parameters:
16
- context: dict - Template context containing variables to prompt for
17
- no_input: bool - Skip prompts and use defaults if True
18
19
Returns:
20
dict - Dictionary of user responses to prompts
21
"""
22
23
def prompt_choice_for_config(cookiecutter_dict, env, key, options, no_input, prompts=None, prefix=""):
24
"""
25
Prompt for config choice from a list of options.
26
27
Parameters:
28
- cookiecutter_dict: dict - Current cookiecutter context
29
- env: Environment - Jinja2 environment for rendering
30
- key: str - Configuration key being prompted for
31
- options: list - Available choices
32
- no_input: bool - Skip prompt if True
33
- prompts: dict, optional - Custom prompt text
34
- prefix: str - Prefix for prompt display
35
36
Returns:
37
str - Selected choice
38
"""
39
```
40
41
### Variable Input Functions
42
43
Functions for different types of user input.
44
45
```python { .api }
46
def read_user_variable(var_name, default_value, prompts=None, prefix=""):
47
"""
48
Prompt user for variable input.
49
50
Parameters:
51
- var_name: str - Name of variable to prompt for
52
- default_value: Any - Default value to use
53
- prompts: dict, optional - Custom prompt messages
54
- prefix: str - Prefix for prompt display
55
56
Returns:
57
str - User input or default value
58
"""
59
60
def read_user_yes_no(var_name, default_value, prompts=None, prefix=""):
61
"""
62
Prompt for yes/no response.
63
64
Parameters:
65
- var_name: str - Name of variable to prompt for
66
- default_value: bool - Default boolean value
67
- prompts: dict, optional - Custom prompt messages
68
- prefix: str - Prefix for prompt display
69
70
Returns:
71
bool - User's yes/no response
72
"""
73
74
def read_user_choice(var_name, options, prompts=None, prefix=""):
75
"""
76
Prompt user to choose from options.
77
78
Parameters:
79
- var_name: str - Name of variable to prompt for
80
- options: list - List of available choices
81
- prompts: dict, optional - Custom prompt messages
82
- prefix: str - Prefix for prompt display
83
84
Returns:
85
str - Selected option
86
"""
87
88
def read_user_dict(var_name, default_value, prompts=None, prefix=""):
89
"""
90
Prompt for dictionary input.
91
92
Parameters:
93
- var_name: str - Name of variable to prompt for
94
- default_value: dict - Default dictionary value
95
- prompts: dict, optional - Custom prompt messages
96
- prefix: str - Prefix for prompt display
97
98
Returns:
99
dict - User-provided dictionary
100
"""
101
```
102
103
### Special Input Functions
104
105
Specialized prompting functions for specific use cases.
106
107
```python { .api }
108
def read_repo_password(question):
109
"""
110
Prompt for password input.
111
112
Parameters:
113
- question: str - Password prompt question
114
115
Returns:
116
str - Password entered by user (input hidden)
117
"""
118
119
def process_json(user_value, default_value=None):
120
"""
121
Load user input as JSON dict.
122
123
Parameters:
124
- user_value: str - JSON string from user input
125
- default_value: Any, optional - Default value if parsing fails
126
127
Returns:
128
dict - Parsed JSON dictionary
129
"""
130
```
131
132
### Template and Context Functions
133
134
Functions for handling template selection and variable rendering.
135
136
```python { .api }
137
def render_variable(env, raw, cookiecutter_dict):
138
"""
139
Render variable for user prompt.
140
141
Parameters:
142
- env: Environment - Jinja2 environment
143
- raw: str - Raw template variable string
144
- cookiecutter_dict: dict - Current cookiecutter context
145
146
Returns:
147
Any - Rendered variable value
148
"""
149
150
def prompt_choice_for_template(key, options, no_input):
151
"""
152
Prompt for template selection.
153
154
Parameters:
155
- key: str - Template key
156
- options: list - Available template options
157
- no_input: bool - Skip prompt if True
158
159
Returns:
160
str - Selected template
161
"""
162
163
def choose_nested_template(context, repo_dir, no_input=False):
164
"""
165
Prompt for nested template selection.
166
167
Parameters:
168
- context: dict - Template context
169
- repo_dir: str - Repository directory
170
- no_input: bool - Skip prompts if True
171
172
Returns:
173
str - Path to selected nested template
174
"""
175
176
def prompt_and_delete(path, no_input=False):
177
"""
178
Ask user about deleting existing files.
179
180
Parameters:
181
- path: str - Path to potentially delete
182
- no_input: bool - Skip prompt if True
183
184
Returns:
185
bool - True if user wants to delete
186
"""
187
```
188
189
## Prompt Classes
190
191
Custom prompt classes for specialized input types.
192
193
```python { .api }
194
class YesNoPrompt(Confirm):
195
"""Boolean prompt for yes/no questions."""
196
197
class JsonPrompt(PromptBase[dict]):
198
"""Prompt that returns dict from JSON string."""
199
```
200
201
## Constants
202
203
```python { .api }
204
DEFAULT_DISPLAY: str # Default display string ('default')
205
```
206
207
## Usage Examples
208
209
### Basic Variable Prompting
210
211
```python
212
from cookiecutter.prompt import read_user_variable, read_user_yes_no, read_user_choice
213
214
# Simple text input
215
project_name = read_user_variable(
216
var_name='project_name',
217
default_value='my-project',
218
prompts={'project_name': 'What is your project name?'}
219
)
220
221
# Yes/no prompt
222
use_docker = read_user_yes_no(
223
var_name='use_docker',
224
default_value=True,
225
prompts={'use_docker': 'Do you want Docker support?'}
226
)
227
228
# Choice from options
229
license_type = read_user_choice(
230
var_name='license',
231
options=['MIT', 'Apache-2.0', 'GPL-3.0', 'BSD-3-Clause'],
232
prompts={'license': 'Choose a license for your project'}
233
)
234
```
235
236
### Complete Configuration Prompting
237
238
```python
239
from cookiecutter.prompt import prompt_for_config
240
from cookiecutter.generate import generate_context
241
242
# Generate context from cookiecutter.json
243
context = generate_context('./template/cookiecutter.json')
244
245
# Prompt user for all configuration values
246
user_config = prompt_for_config(context, no_input=False)
247
248
print("User provided configuration:")
249
for key, value in user_config.items():
250
print(f" {key}: {value}")
251
```
252
253
### Advanced Input Types
254
255
```python
256
from cookiecutter.prompt import read_user_dict, process_json
257
258
# Dictionary input
259
database_config = read_user_dict(
260
var_name='database_settings',
261
default_value={'host': 'localhost', 'port': 5432},
262
prompts={'database_settings': 'Enter database configuration as JSON'}
263
)
264
265
# JSON processing
266
json_input = '{"name": "test", "version": "1.0.0"}'
267
parsed_config = process_json(json_input, default_value={})
268
```
269
270
### Custom Prompts with Context
271
272
```python
273
from cookiecutter.prompt import render_variable, prompt_choice_for_config
274
from cookiecutter.environment import StrictEnvironment
275
276
# Set up Jinja2 environment
277
env = StrictEnvironment()
278
279
# Render dynamic variable
280
cookiecutter_dict = {'project_name': 'my-project', 'year': '2024'}
281
rendered_value = render_variable(
282
env=env,
283
raw='{{cookiecutter.project_name}}-{{cookiecutter.year}}',
284
cookiecutter_dict=cookiecutter_dict
285
)
286
# Returns: 'my-project-2024'
287
288
# Dynamic choice prompting
289
framework_choice = prompt_choice_for_config(
290
cookiecutter_dict=cookiecutter_dict,
291
env=env,
292
key='framework',
293
options=['django', 'flask', 'fastapi'],
294
no_input=False,
295
prompts={'framework': 'Select a web framework'}
296
)
297
```
298
299
### Password and Security
300
301
```python
302
from cookiecutter.prompt import read_repo_password
303
304
# Secure password input
305
repo_password = read_repo_password(
306
"Enter password for private repository: "
307
)
308
# Password input is hidden from terminal display
309
```
310
311
### Template Selection
312
313
```python
314
from cookiecutter.prompt import choose_nested_template, prompt_choice_for_template
315
316
# Choose from nested templates
317
context = {
318
'cookiecutter': {
319
'template': ['basic', 'advanced', 'minimal'],
320
'templates': {
321
'basic': './templates/basic',
322
'advanced': './templates/advanced',
323
'minimal': './templates/minimal'
324
}
325
}
326
}
327
328
selected_template = choose_nested_template(
329
context=context,
330
repo_dir='./template-repo',
331
no_input=False
332
)
333
```
334
335
### Handling Existing Files
336
337
```python
338
from cookiecutter.prompt import prompt_and_delete
339
import os
340
341
output_path = './my-new-project'
342
if os.path.exists(output_path):
343
should_delete = prompt_and_delete(output_path, no_input=False)
344
if should_delete:
345
import shutil
346
shutil.rmtree(output_path)
347
print(f"Deleted existing directory: {output_path}")
348
else:
349
print("Keeping existing directory")
350
```
351
352
### No-Input Mode
353
354
```python
355
from cookiecutter.prompt import prompt_for_config
356
357
# Skip all prompts and use defaults
358
context = generate_context('./template/cookiecutter.json')
359
default_config = prompt_for_config(context, no_input=True)
360
361
# All values will be defaults from cookiecutter.json
362
print("Using default configuration:")
363
for key, value in default_config.items():
364
print(f" {key}: {value}")
365
```
366
367
### Custom Prompt Messages
368
369
```python
370
from cookiecutter.prompt import read_user_variable
371
372
# Custom prompt with detailed help
373
custom_prompts = {
374
'author_email': 'Enter your email address (will be used in setup.py and documentation)',
375
'version': 'Initial version number (use semantic versioning like 0.1.0)',
376
'description': 'Brief description of your project (one line)'
377
}
378
379
author_email = read_user_variable(
380
var_name='author_email',
381
default_value='user@example.com',
382
prompts=custom_prompts
383
)
384
385
version = read_user_variable(
386
var_name='version',
387
default_value='0.1.0',
388
prompts=custom_prompts
389
)
390
```