0
# Template Processing
1
2
Context generation, file rendering, and template discovery functionality that powers cookiecutter's core template processing capabilities. This module handles the transformation of template directories into fully-rendered project structures.
3
4
## Capabilities
5
6
### Context Generation
7
8
Generate template context from cookiecutter.json files and user input.
9
10
```python { .api }
11
def generate_context(context_file='cookiecutter.json', default_context=None, extra_context=None):
12
"""
13
Generate context for template processing.
14
15
Parameters:
16
- context_file: str - Path to cookiecutter.json file
17
- default_context: dict, optional - Default context values
18
- extra_context: dict, optional - Additional context to override defaults
19
20
Returns:
21
dict - Generated context dictionary with 'cookiecutter' key containing template variables
22
"""
23
24
def apply_overwrites_to_context(context, overwrite_context, *, in_dictionary_variable=False):
25
"""
26
Modify context with overrides.
27
28
Parameters:
29
- context: dict - Original context dictionary
30
- overwrite_context: dict - Values to override in context
31
- in_dictionary_variable: bool - Whether we're inside a dictionary variable
32
33
Returns:
34
dict - Modified context with overrides applied
35
"""
36
```
37
38
### File Generation
39
40
Core template rendering and file creation functionality.
41
42
```python { .api }
43
def generate_files(
44
repo_dir,
45
context=None,
46
output_dir='.',
47
overwrite_if_exists=False,
48
skip_if_file_exists=False,
49
accept_hooks=True,
50
keep_project_on_failure=False
51
):
52
"""
53
Main function to render templates and save to files.
54
55
Parameters:
56
- repo_dir: str - Path to repository directory containing template
57
- context: dict, optional - Template context dictionary
58
- output_dir: str - Directory to output generated project
59
- overwrite_if_exists: bool - Overwrite existing output directory
60
- skip_if_file_exists: bool - Skip files that already exist
61
- accept_hooks: bool - Execute pre/post generation hooks
62
- keep_project_on_failure: bool - Keep project directory on failure
63
64
Returns:
65
str - Path to generated project directory
66
"""
67
68
def generate_file(project_dir, infile, context, env, skip_if_file_exists=False):
69
"""
70
Render and generate individual files.
71
72
Parameters:
73
- project_dir: str - Path to project directory
74
- infile: str - Input template file path
75
- context: dict - Template context
76
- env: Environment - Jinja2 environment for rendering
77
- skip_if_file_exists: bool - Skip if output file already exists
78
"""
79
80
def render_and_create_dir(dirname, context, output_dir, environment, overwrite_if_exists=False):
81
"""
82
Render directory name and create it.
83
84
Parameters:
85
- dirname: str - Template directory name to render
86
- context: dict - Template context
87
- output_dir: str - Output directory path
88
- environment: Environment - Jinja2 environment
89
- overwrite_if_exists: bool - Overwrite if directory exists
90
91
Returns:
92
str - Path to created directory
93
"""
94
```
95
96
### Template Discovery
97
98
Locate and validate cookiecutter templates.
99
100
```python { .api }
101
def find_template(repo_dir, env):
102
"""
103
Determine which directory is the project template.
104
105
Parameters:
106
- repo_dir: str - Repository directory to search
107
- env: Environment - Jinja2 environment for template validation
108
109
Returns:
110
str - Path to template directory
111
"""
112
```
113
114
### Copy Control
115
116
Control which files are copied vs rendered as templates.
117
118
```python { .api }
119
def is_copy_only_path(path, context):
120
"""
121
Check if path should only be copied, not rendered.
122
123
Parameters:
124
- path: str - File or directory path to check
125
- context: dict - Template context containing copy settings
126
127
Returns:
128
bool - True if path should be copied without rendering
129
"""
130
```
131
132
## Template Structure
133
134
Cookiecutter templates follow a specific directory structure:
135
136
```
137
template-directory/
138
├── cookiecutter.json # Template configuration
139
├── hooks/ # Pre/post generation scripts (optional)
140
│ ├── pre_gen_project.py
141
│ └── post_gen_project.py
142
└── {{cookiecutter.project_name}}/ # Template directory
143
├── {{cookiecutter.module_name}}/
144
│ ├── __init__.py
145
│ └── {{cookiecutter.module_name}}.py
146
├── tests/
147
├── setup.py
148
└── README.md
149
```
150
151
## Usage Examples
152
153
### Basic Context Generation
154
155
```python
156
from cookiecutter.generate import generate_context
157
158
# Generate context from cookiecutter.json
159
context = generate_context('path/to/cookiecutter.json')
160
161
# Context with defaults
162
default_ctx = {'author': 'Default Author', 'version': '1.0.0'}
163
context = generate_context(
164
'path/to/cookiecutter.json',
165
default_context=default_ctx
166
)
167
168
# Context with extra overrides
169
extra_ctx = {'project_name': 'my-awesome-project'}
170
context = generate_context(
171
'path/to/cookiecutter.json',
172
extra_context=extra_ctx
173
)
174
```
175
176
### Template Processing
177
178
```python
179
from cookiecutter.generate import generate_files, find_template
180
from cookiecutter.environment import StrictEnvironment
181
182
# Find template directory
183
env = StrictEnvironment()
184
template_dir = find_template('./my-template-repo', env)
185
186
# Generate files from template
187
context = {
188
'cookiecutter': {
189
'project_name': 'my-project',
190
'author': 'Jane Developer',
191
'version': '1.0.0'
192
}
193
}
194
195
result_path = generate_files(
196
repo_dir=template_dir,
197
context=context,
198
output_dir='./output',
199
overwrite_if_exists=True
200
)
201
```
202
203
### Advanced File Generation
204
205
```python
206
from cookiecutter.generate import generate_files
207
import os
208
209
# Generate with custom settings
210
context = generate_context('./template/cookiecutter.json')
211
212
# Add runtime context
213
context['cookiecutter'].update({
214
'timestamp': '2024-01-01',
215
'user_home': os.path.expanduser('~')
216
})
217
218
# Generate with hooks disabled
219
result_path = generate_files(
220
repo_dir='./template',
221
context=context,
222
output_dir='./projects',
223
accept_hooks=False,
224
skip_if_file_exists=True
225
)
226
227
print(f"Project generated at: {result_path}")
228
```
229
230
### Copy-Only Files
231
232
```python
233
from cookiecutter.generate import generate_context, is_copy_only_path
234
235
# Set up context with copy-only patterns
236
context = generate_context('./template/cookiecutter.json')
237
238
# Check if specific files should be copied without rendering
239
binary_file = 'assets/logo.png'
240
config_file = 'config/app.json'
241
242
if is_copy_only_path(binary_file, context):
243
print(f"{binary_file} will be copied without rendering")
244
245
if is_copy_only_path(config_file, context):
246
print(f"{config_file} will be copied without rendering")
247
```
248
249
### Context Manipulation
250
251
```python
252
from cookiecutter.generate import apply_overwrites_to_context, generate_context
253
254
# Generate base context
255
base_context = generate_context('./template/cookiecutter.json')
256
257
# Apply runtime overrides
258
overrides = {
259
'project_name': 'runtime-project',
260
'features': {
261
'database': True,
262
'authentication': True
263
}
264
}
265
266
final_context = apply_overwrites_to_context(
267
base_context,
268
overrides
269
)
270
271
# Context now includes runtime overrides
272
print(final_context['cookiecutter']['project_name']) # 'runtime-project'
273
```
274
275
### Error Handling
276
277
```python
278
from cookiecutter.generate import generate_files, find_template
279
from cookiecutter.exceptions import (
280
UnknownTemplateDirException,
281
MissingProjectDir,
282
UndefinedVariableInTemplate
283
)
284
285
try:
286
# Find and validate template
287
template_dir = find_template('./template-repo', env)
288
289
# Generate files
290
result = generate_files(
291
repo_dir=template_dir,
292
context=context,
293
output_dir='./output'
294
)
295
296
except UnknownTemplateDirException:
297
print("Could not determine template directory")
298
except MissingProjectDir:
299
print("Generated project directory is missing")
300
except UndefinedVariableInTemplate as e:
301
print(f"Template uses undefined variable: {e}")
302
```