0
# Configuration System
1
2
Application framework and configuration management including configurable base classes, config file loading, and command-line argument processing. This provides a complete system for building configurable applications with the IPython/Jupyter ecosystem.
3
4
## Capabilities
5
6
### Application Classes
7
8
Base classes for building configurable applications with command-line interface support.
9
10
```python { .api }
11
class Application(SingletonConfigurable):
12
"""
13
Singleton application with full configuration support.
14
15
Provides a complete application framework with configuration
16
file loading, command-line argument parsing, logging setup,
17
and plugin management.
18
"""
19
20
# Key attributes
21
name = Unicode(u'application')
22
description = Unicode(u'')
23
version = Unicode(u'0.0')
24
classes = List()
25
aliases = Dict()
26
flags = Dict()
27
config = Instance(Config)
28
29
def initialize(self, argv=None):
30
"""
31
Basic configuration setup.
32
33
Parses command line, loads config files, and initializes
34
the application with the resulting configuration.
35
36
Parameters:
37
- argv: list|None - Command line arguments (sys.argv if None)
38
"""
39
40
def start(self):
41
"""
42
Start the application mainloop.
43
44
Override this method in subclasses to implement the main
45
application logic. Called after initialization is complete.
46
"""
47
48
def parse_command_line(self, argv=None):
49
"""
50
Parse command line arguments.
51
52
Processes command line flags and aliases to update
53
configuration. Handles --help and --version automatically.
54
55
Parameters:
56
- argv: list|None - Arguments to parse (sys.argv if None)
57
"""
58
59
def load_config_file(self, filename, path=None):
60
"""
61
Load configuration from file.
62
63
Supports Python config files (.py) and JSON config files (.json).
64
Merges loaded configuration with existing config.
65
66
Parameters:
67
- filename: str - Config file name
68
- path: str|list|None - Search paths for config file
69
"""
70
71
def print_help(self, classes=False):
72
"""
73
Print application help message.
74
75
Shows usage, description, command line flags, aliases,
76
and optionally detailed help for configurable classes.
77
78
Parameters:
79
- classes: bool - Whether to show help for configurable classes
80
"""
81
82
@classmethod
83
def launch_instance(cls, argv=None, **kwargs):
84
"""
85
Class method to launch application instance.
86
87
Creates an instance, initializes it, and starts it.
88
Commonly used pattern for application entry points.
89
90
Parameters:
91
- argv: list|None - Command line arguments
92
- **kwargs: Additional arguments passed to constructor
93
"""
94
95
class ApplicationError(Exception):
96
"""Exception raised by Application classes."""
97
98
class LevelFormatter(logging.Formatter):
99
"""
100
Logging formatter with highlevel field.
101
102
Provides enhanced logging formatting for applications
103
with support for different log levels and highlighting.
104
"""
105
```
106
107
### Configurable Base Classes
108
109
Base classes for objects that can be configured through the configuration system.
110
111
```python { .api }
112
class Configurable(HasTraits):
113
"""
114
Base class for configurable objects.
115
116
Integrates with the configuration system to allow objects
117
to be configured through config files and command line arguments.
118
"""
119
120
config = Instance(Config)
121
parent = Instance('traitlets.config.configurable.Configurable', allow_none=True)
122
123
def __init__(self, config=None, parent=None, **kwargs):
124
"""
125
Initialize configurable object.
126
127
Parameters:
128
- config: Config|None - Configuration object
129
- parent: Configurable|None - Parent configurable object
130
- **kwargs: Additional trait values
131
"""
132
133
class ConfigurableError(Exception):
134
"""Exception raised by Configurable classes."""
135
136
class MultipleInstanceError(ConfigurableError):
137
"""Exception raised when multiple instances are not allowed."""
138
139
class LoggingConfigurable(Configurable):
140
"""
141
Configurable base class with logging support.
142
143
Adds logging capabilities to configurable objects with
144
automatic logger setup and configuration.
145
"""
146
147
class SingletonConfigurable(LoggingConfigurable):
148
"""
149
Singleton version of LoggingConfigurable.
150
151
Ensures only one instance exists per class, commonly used
152
for application and manager classes.
153
"""
154
```
155
156
### Configuration Classes
157
158
Classes for managing configuration data.
159
160
```python { .api }
161
class Config(dict):
162
"""
163
Configuration object for storing config data.
164
165
Dictionary-like object with special behavior for configuration
166
including merging, collision detection, and nested access.
167
"""
168
169
def merge(self, other):
170
"""
171
Merge with another config object.
172
173
Recursively merges configuration data, with values from
174
other config taking precedence over existing values.
175
176
Parameters:
177
- other: Config - Configuration to merge
178
"""
179
180
def collisions(self, other):
181
"""
182
Find colliding keys with another config.
183
184
Returns dictionary of keys that exist in both configs
185
with different values.
186
187
Parameters:
188
- other: Config - Configuration to compare
189
190
Returns:
191
dict - Colliding keys and values
192
"""
193
194
class LazyConfigValue:
195
"""
196
Lazy evaluation of config values.
197
198
Defers evaluation of configuration values until they are
199
actually needed, enabling complex configuration expressions.
200
"""
201
```
202
203
### Configuration Loaders
204
205
Classes for loading configuration from various sources.
206
207
```python { .api }
208
class ConfigLoader:
209
"""Base class for configuration loaders."""
210
211
def load_config(self):
212
"""
213
Load configuration data.
214
215
Returns:
216
Config - Loaded configuration object
217
"""
218
219
class FileConfigLoader(ConfigLoader):
220
"""Base class for file-based configuration loaders."""
221
222
class JSONFileConfigLoader(FileConfigLoader):
223
"""
224
Load configuration from JSON files.
225
226
Supports loading configuration data from JSON format files
227
with automatic type conversion and validation.
228
"""
229
230
class PyFileConfigLoader(FileConfigLoader):
231
"""
232
Load configuration from Python files.
233
234
Executes Python configuration files and extracts configuration
235
objects, allowing for dynamic configuration generation.
236
"""
237
238
class CommandLineConfigLoader(ConfigLoader):
239
"""Base class for command line configuration loaders."""
240
241
class KeyValueConfigLoader(CommandLineConfigLoader):
242
"""
243
Load configuration from key-value pairs.
244
245
Processes command line arguments in key=value format
246
and converts them to configuration data.
247
"""
248
249
class ArgParseConfigLoader(CommandLineConfigLoader):
250
"""
251
Load configuration using argparse.
252
253
Integrates with Python's argparse module for sophisticated
254
command line argument processing.
255
"""
256
257
class KVArgParseConfigLoader(ArgParseConfigLoader):
258
"""
259
Key-value argparse configuration loader.
260
261
Combines argparse functionality with key-value configuration
262
for flexible command line processing.
263
"""
264
```
265
266
### Configuration Exceptions
267
268
Exception classes for configuration errors.
269
270
```python { .api }
271
class ConfigError(Exception):
272
"""Base exception for configuration errors."""
273
274
class ConfigLoaderError(ConfigError):
275
"""Exception raised by configuration loaders."""
276
277
class ConfigFileNotFound(ConfigLoaderError):
278
"""Exception raised when configuration file is not found."""
279
280
class ArgumentError(ConfigLoaderError):
281
"""Exception raised for command line argument errors."""
282
```
283
284
### Configuration Manager
285
286
Classes for managing configuration persistence.
287
288
```python { .api }
289
class BaseJSONConfigManager:
290
"""
291
JSON configuration file manager.
292
293
Provides methods for storing and retrieving configuration
294
data in JSON format with atomic file operations.
295
"""
296
297
def get(self, section_name):
298
"""
299
Retrieve configuration data for a section.
300
301
Parameters:
302
- section_name: str - Configuration section name
303
304
Returns:
305
dict - Configuration data for the section
306
"""
307
308
def set(self, section_name, data):
309
"""
310
Store configuration data for a section.
311
312
Parameters:
313
- section_name: str - Configuration section name
314
- data: dict - Configuration data to store
315
"""
316
317
def update(self, section_name, new_data):
318
"""
319
Update configuration section with new data.
320
321
Merges new data with existing configuration data
322
for the specified section.
323
324
Parameters:
325
- section_name: str - Configuration section name
326
- new_data: dict - New data to merge
327
"""
328
```
329
330
### Configuration Utilities
331
332
Utility functions for configuration management.
333
334
```python { .api }
335
def catch_config_error(method):
336
"""
337
Decorator for catching configuration errors during initialization.
338
339
Wraps methods to catch and handle configuration errors gracefully,
340
typically used on Application.initialize methods.
341
342
Parameters:
343
- method: callable - Method to wrap
344
345
Returns:
346
callable - Decorated method
347
"""
348
349
def boolean_flag(name, configurable, set_help='', unset_help=''):
350
"""
351
Helper for building --trait/--no-trait flag pairs.
352
353
Creates a dictionary of command line flags for boolean traits
354
that can be used in Application.flags.
355
356
Parameters:
357
- name: str - Flag name
358
- configurable: str - Configurable class name
359
- set_help: str - Help text for --flag
360
- unset_help: str - Help text for --no-flag
361
362
Returns:
363
dict - Flag configuration dictionary
364
"""
365
366
def get_config():
367
"""
368
Get configuration object for global Application instance.
369
370
Returns the configuration from the currently running Application
371
instance, if one exists.
372
373
Returns:
374
Config|None - Global application configuration
375
"""
376
377
def recursive_update(target, new):
378
"""
379
Recursively update dictionaries.
380
381
Deep merge two dictionaries, updating nested structures
382
while preserving existing keys not in the new dictionary.
383
384
Parameters:
385
- target: dict - Dictionary to update
386
- new: dict - New values to merge
387
"""
388
```
389
390
## Usage Examples
391
392
### Basic Application
393
394
```python
395
from traitlets.config import Application
396
from traitlets import Unicode, Int, Bool
397
398
class MyApp(Application):
399
name = Unicode(u'myapp')
400
description = Unicode(u'A sample configurable application')
401
version = Unicode(u'1.0.0')
402
403
# Configurable traits
404
host = Unicode(u'localhost', help="Server host").tag(config=True)
405
port = Int(8080, help="Server port").tag(config=True)
406
debug = Bool(False, help="Debug mode").tag(config=True)
407
408
# Command line aliases
409
aliases = {
410
'host': 'MyApp.host',
411
'port': 'MyApp.port',
412
}
413
414
# Command line flags
415
flags = {
416
'debug': ({'MyApp': {'debug': True}}, "Enable debug mode"),
417
}
418
419
def start(self):
420
print(f"Starting {self.name} v{self.version}")
421
print(f"Host: {self.host}")
422
print(f"Port: {self.port}")
423
print(f"Debug: {self.debug}")
424
425
if __name__ == '__main__':
426
MyApp.launch_instance()
427
```
428
429
### Configuration Files
430
431
Python configuration file (`myapp_config.py`):
432
433
```python
434
c = get_config()
435
436
c.MyApp.host = '0.0.0.0'
437
c.MyApp.port = 9000
438
c.MyApp.debug = True
439
```
440
441
JSON configuration file (`myapp_config.json`):
442
443
```json
444
{
445
"MyApp": {
446
"host": "0.0.0.0",
447
"port": 9000,
448
"debug": true
449
}
450
}
451
```
452
453
### Configurable Classes
454
455
```python
456
from traitlets.config import Configurable
457
from traitlets import Unicode, Int, List
458
459
class DatabaseConfig(Configurable):
460
host = Unicode(u'localhost', help="Database host").tag(config=True)
461
port = Int(5432, help="Database port").tag(config=True)
462
username = Unicode(help="Database username").tag(config=True)
463
databases = List(Unicode(), help="Database names").tag(config=True)
464
465
class WebConfig(Configurable):
466
bind_host = Unicode(u'127.0.0.1', help="Web server bind host").tag(config=True)
467
bind_port = Int(8000, help="Web server bind port").tag(config=True)
468
static_path = Unicode(u'./static', help="Static files path").tag(config=True)
469
470
class MyApplication(Application):
471
classes = [DatabaseConfig, WebConfig]
472
473
aliases = {
474
'db-host': 'DatabaseConfig.host',
475
'db-port': 'DatabaseConfig.port',
476
'web-host': 'WebConfig.bind_host',
477
'web-port': 'WebConfig.bind_port',
478
}
479
480
# Usage: python myapp.py --db-host=db.example.com --web-port=9000
481
```
482
483
### Configuration Manager
484
485
```python
486
from traitlets.config.manager import BaseJSONConfigManager
487
import tempfile
488
import os
489
490
# Create temporary config directory
491
config_dir = tempfile.mkdtemp()
492
config_manager = BaseJSONConfigManager(config_dir=config_dir)
493
494
# Store configuration
495
app_config = {
496
'host': 'example.com',
497
'port': 8080,
498
'features': ['auth', 'logging']
499
}
500
501
config_manager.set('myapp', app_config)
502
503
# Retrieve configuration
504
loaded_config = config_manager.get('myapp')
505
print(loaded_config) # {'host': 'example.com', 'port': 8080, 'features': ['auth', 'logging']}
506
507
# Update configuration
508
config_manager.update('myapp', {'debug': True, 'port': 9000})
509
510
updated_config = config_manager.get('myapp')
511
print(updated_config) # Includes debug=True and port=9000
512
513
# Cleanup
514
import shutil
515
shutil.rmtree(config_dir)
516
```
517
518
### Advanced Application with Subcommands
519
520
```python
521
from traitlets.config import Application
522
from traitlets import Unicode, List, Dict
523
524
class SubcommandApp(Application):
525
name = Unicode(u'myapp')
526
527
subcommands = Dict({
528
'init': ('myapp.InitCommand', "Initialize new project"),
529
'serve': ('myapp.ServeCommand', "Start web server"),
530
'deploy': ('myapp.DeployCommand', "Deploy application"),
531
})
532
533
def start(self):
534
if self.subapp:
535
self.subapp.start()
536
else:
537
self.print_help()
538
539
class InitCommand(Application):
540
name = Unicode(u'init')
541
project_name = Unicode(help="Project name").tag(config=True)
542
543
aliases = {'name': 'InitCommand.project_name'}
544
545
def start(self):
546
print(f"Initializing project: {self.project_name}")
547
548
class ServeCommand(Application):
549
name = Unicode(u'serve')
550
host = Unicode(u'localhost').tag(config=True)
551
port = Int(8000).tag(config=True)
552
553
def start(self):
554
print(f"Serving on {self.host}:{self.port}")
555
556
# Usage:
557
# python myapp.py init --name=myproject
558
# python myapp.py serve --port=9000
559
```
560
561
### Custom Configuration Loader
562
563
```python
564
from traitlets.config.loader import ConfigLoader
565
from traitlets.config import Config
566
import yaml
567
568
class YAMLConfigLoader(ConfigLoader):
569
def __init__(self, filename):
570
self.filename = filename
571
572
def load_config(self):
573
with open(self.filename, 'r') as f:
574
data = yaml.safe_load(f)
575
576
config = Config()
577
for section, values in data.items():
578
config[section] = values
579
580
return config
581
582
# Usage with Application
583
class YAMLApp(Application):
584
def load_config_file(self, filename, path=None):
585
if filename.endswith('.yaml') or filename.endswith('.yml'):
586
loader = YAMLConfigLoader(filename)
587
config = loader.load_config()
588
self.config.merge(config)
589
else:
590
super().load_config_file(filename, path)
591
```