0
# Configuration Loading
1
2
Flexible configuration loading from YAML files, Python modules, and programmatic sources to manage complex asset processing setups.
3
4
## Capabilities
5
6
### YAML Configuration Loading
7
8
Load environment and bundle configurations from YAML files for declarative asset management.
9
10
```python { .api }
11
class YAMLLoader:
12
def __init__(self, file_or_filename):
13
"""
14
Create YAML configuration loader.
15
16
Parameters:
17
- file_or_filename: YAML file path or file object
18
"""
19
20
def load_bundles(self):
21
"""
22
Load bundle definitions from YAML.
23
24
Returns:
25
Dictionary of bundle name -> Bundle instance mappings
26
"""
27
28
def load_environment(self):
29
"""
30
Load complete environment configuration from YAML.
31
32
Returns:
33
Configured Environment instance
34
"""
35
```
36
37
Example YAML configuration:
38
```yaml
39
# assets.yaml
40
directory: ./static
41
url: /static
42
debug: false
43
cache: filesystem
44
auto_build: true
45
46
bundles:
47
js_all:
48
contents:
49
- js/jquery.js
50
- js/app.js
51
- js/utils.js
52
filters: jsmin
53
output: gen/app.js
54
55
css_all:
56
contents:
57
- css/base.css
58
- css/layout.css
59
filters:
60
- sass
61
- cssmin
62
output: gen/style.css
63
depends:
64
- css/_variables.scss
65
- css/_mixins.scss
66
```
67
68
Usage example:
69
```python
70
from webassets.loaders import YAMLLoader
71
72
# Load from YAML file
73
loader = YAMLLoader('assets.yaml')
74
75
# Load environment and bundles
76
env = loader.load_environment()
77
bundles = loader.load_bundles()
78
79
# Register bundles
80
for name, bundle in bundles.items():
81
env.register(name, bundle)
82
83
# Build all bundles
84
for bundle in bundles.values():
85
bundle.build()
86
```
87
88
### Python Module Loading
89
90
Load configurations from Python modules for dynamic and programmatic asset definitions.
91
92
```python { .api }
93
class PythonLoader:
94
def __init__(self, module_name):
95
"""
96
Create Python module configuration loader.
97
98
Parameters:
99
- module_name: Python module name to import
100
"""
101
102
def load_bundles(self):
103
"""Load bundles defined in Python module."""
104
105
def load_environment(self):
106
"""Load environment configuration from Python module."""
107
```
108
109
Example Python configuration:
110
```python
111
# assets.py
112
from webassets import Environment, Bundle
113
114
# Environment configuration
115
directory = './static'
116
url = '/static'
117
debug = False
118
cache = True
119
120
# Bundle definitions
121
bundles = {
122
'js_all': Bundle(
123
'jquery.js',
124
'app.js',
125
'utils.js',
126
filters='jsmin',
127
output='gen/app.js'
128
),
129
130
'css_all': Bundle(
131
'base.css',
132
'layout.css',
133
filters=['sass', 'cssmin'],
134
output='gen/style.css'
135
)
136
}
137
138
# Environment setup
139
def create_environment():
140
env = Environment(directory, url, debug=debug, cache=cache)
141
for name, bundle in bundles.items():
142
env.register(name, bundle)
143
return env
144
```
145
146
Usage example:
147
```python
148
from webassets.loaders import PythonLoader
149
150
# Load from Python module
151
loader = PythonLoader('myapp.assets')
152
env = loader.load_environment()
153
154
# Environment is ready to use
155
js_urls = env['js_all'].urls()
156
```
157
158
### Glob Pattern Loading
159
160
Load and organize assets using glob patterns for automatic file discovery.
161
162
```python { .api }
163
class GlobLoader:
164
def __init__(self, pattern, **bundle_options):
165
"""
166
Create glob pattern loader.
167
168
Parameters:
169
- pattern: Glob pattern for file matching
170
- **bundle_options: Options for created bundles
171
"""
172
173
def load_bundles(self):
174
"""Load bundles from glob pattern matches."""
175
```
176
177
Example usage:
178
```python
179
from webassets.loaders import GlobLoader
180
181
# Load all JavaScript files
182
js_loader = GlobLoader(
183
'js/**/*.js',
184
filters='jsmin',
185
output='gen/all.js'
186
)
187
188
# Load all CSS files
189
css_loader = GlobLoader(
190
'css/**/*.css',
191
filters=['sass', 'cssmin'],
192
output='gen/all.css'
193
)
194
195
js_bundles = js_loader.load_bundles()
196
css_bundles = css_loader.load_bundles()
197
```
198
199
### Base Loader Class
200
201
Foundation class for creating custom configuration loaders.
202
203
```python { .api }
204
class Loader:
205
def load_bundles(self):
206
"""Override to load bundle definitions."""
207
raise NotImplementedError()
208
209
def load_environment(self):
210
"""Override to load environment configuration."""
211
raise NotImplementedError()
212
```
213
214
### Loader Exceptions
215
216
Exception handling for configuration loading errors.
217
218
```python { .api }
219
class LoaderError(Exception):
220
"""Raised when loaders can't process a file."""
221
```
222
223
## Advanced Configuration Examples
224
225
### Complex YAML Configuration
226
227
```yaml
228
# Full-featured assets.yaml
229
directory: ./src/assets
230
url: /assets
231
debug: false
232
cache:
233
type: filesystem
234
directory: ./.webassets-cache
235
auto_build: false
236
versions: hash
237
manifest: json:manifest.json
238
239
load_path:
240
- ./vendor
241
- ./node_modules
242
243
url_mapping:
244
/images: ./img
245
/fonts: ./fonts
246
247
bundles:
248
# Vendor JavaScript
249
js_vendor:
250
contents:
251
- vendor/jquery/dist/jquery.min.js
252
- vendor/bootstrap/dist/js/bootstrap.min.js
253
- vendor/lodash/lodash.min.js
254
output: gen/vendor-%(version)s.js
255
256
# Application JavaScript
257
js_app:
258
contents:
259
- js/app.js
260
- js/modules/*.js
261
- js/utils.js
262
filters:
263
- babel
264
- uglifyjs
265
output: gen/app-%(version)s.js
266
depends:
267
- js/config.js
268
269
# Vendor CSS
270
css_vendor:
271
contents:
272
- vendor/bootstrap/dist/css/bootstrap.min.css
273
- vendor/font-awesome/css/font-awesome.min.css
274
output: gen/vendor-%(version)s.css
275
276
# Application CSS
277
css_app:
278
contents:
279
- scss/main.scss
280
filters:
281
- libsass
282
- autoprefixer
283
- cssmin
284
output: gen/app-%(version)s.css
285
depends:
286
- scss/_variables.scss
287
- scss/_mixins.scss
288
- scss/components/*.scss
289
```
290
291
### Dynamic Python Configuration
292
293
```python
294
# Dynamic assets.py with environment detection
295
import os
296
from webassets import Environment, Bundle
297
298
# Detect environment
299
DEBUG = os.environ.get('DEBUG', 'false').lower() == 'true'
300
STATIC_ROOT = os.environ.get('STATIC_ROOT', './static')
301
STATIC_URL = os.environ.get('STATIC_URL', '/static')
302
303
# Environment configuration
304
directory = STATIC_ROOT
305
url = STATIC_URL
306
debug = DEBUG
307
cache = not DEBUG
308
auto_build = DEBUG
309
310
def create_js_bundle(debug=False):
311
"""Create JavaScript bundle based on environment."""
312
filters = ['babel']
313
if not debug:
314
filters.append('uglifyjs')
315
316
return Bundle(
317
'js/app.js',
318
'js/utils.js',
319
'js/modules/*.js',
320
filters=filters,
321
output='gen/app.js'
322
)
323
324
def create_css_bundle(debug=False):
325
"""Create CSS bundle based on environment."""
326
filters = ['libsass', 'autoprefixer']
327
if not debug:
328
filters.append('cssmin')
329
330
return Bundle(
331
'scss/main.scss',
332
filters=filters,
333
output='gen/app.css'
334
)
335
336
# Bundle definitions
337
bundles = {
338
'js_app': create_js_bundle(debug),
339
'css_app': create_css_bundle(debug)
340
}
341
342
# Add versioning in production
343
if not debug:
344
for bundle in bundles.values():
345
bundle.output = bundle.output.replace('.', '-%(version)s.')
346
347
def create_environment():
348
env = Environment(
349
directory=directory,
350
url=url,
351
debug=debug,
352
cache=cache,
353
auto_build=auto_build
354
)
355
356
if not debug:
357
env.versions = 'hash'
358
env.manifest = 'json:manifest.json'
359
360
for name, bundle in bundles.items():
361
env.register(name, bundle)
362
363
return env
364
```
365
366
### Custom Loader Implementation
367
368
```python
369
from webassets.loaders import Loader, LoaderError
370
from webassets import Environment, Bundle
371
import json
372
373
class JSONLoader(Loader):
374
"""Load configuration from JSON files."""
375
376
def __init__(self, filename):
377
self.filename = filename
378
379
def load_environment(self):
380
try:
381
with open(self.filename, 'r') as f:
382
config = json.load(f)
383
except (IOError, ValueError) as e:
384
raise LoaderError(f"Failed to load {self.filename}: {e}")
385
386
# Create environment
387
env_config = config.get('environment', {})
388
env = Environment(**env_config)
389
390
# Load bundles
391
bundles_config = config.get('bundles', {})
392
for name, bundle_config in bundles_config.items():
393
contents = bundle_config.pop('contents', [])
394
bundle = Bundle(*contents, **bundle_config)
395
env.register(name, bundle)
396
397
return env
398
399
def load_bundles(self):
400
env = self.load_environment()
401
return dict(env)
402
403
# Usage
404
loader = JSONLoader('assets.json')
405
env = loader.load_environment()
406
```
407
408
### Multi-Source Configuration
409
410
```python
411
def load_assets_config():
412
"""Load assets from multiple sources with precedence."""
413
414
# Start with base configuration
415
base_loader = YAMLLoader('assets.base.yaml')
416
env = base_loader.load_environment()
417
418
# Override with environment-specific config
419
env_config = os.environ.get('ENVIRONMENT', 'development')
420
env_file = f'assets.{env_config}.yaml'
421
422
if os.path.exists(env_file):
423
env_loader = YAMLLoader(env_file)
424
env_bundles = env_loader.load_bundles()
425
426
# Merge bundles
427
for name, bundle in env_bundles.items():
428
env.register(name, bundle)
429
430
# Load additional bundles from Python if available
431
try:
432
python_loader = PythonLoader('local_assets')
433
local_bundles = python_loader.load_bundles()
434
435
for name, bundle in local_bundles.items():
436
env.register(name, bundle)
437
except ImportError:
438
pass # Local assets module not available
439
440
return env
441
```
442
443
### Configuration Validation
444
445
```python
446
def validate_assets_config(config_file):
447
"""Validate assets configuration before loading."""
448
449
try:
450
loader = YAMLLoader(config_file)
451
env = loader.load_environment()
452
bundles = loader.load_bundles()
453
except Exception as e:
454
print(f"Configuration error: {e}")
455
return False
456
457
# Validate bundles
458
for name, bundle in bundles.items():
459
try:
460
# Test bundle resolution
461
bundle.resolve_contents()
462
print(f"Bundle '{name}': OK")
463
except Exception as e:
464
print(f"Bundle '{name}': ERROR - {e}")
465
return False
466
467
print("Configuration validation passed")
468
return True
469
470
# Usage
471
if validate_assets_config('assets.yaml'):
472
loader = YAMLLoader('assets.yaml')
473
env = loader.load_environment()
474
```