0
# Views and Data Access
1
2
Dictionary-like interface for querying configuration data with support for nested access, type conversion, and validation. ConfigView provides the primary API for accessing configuration values with transparent type checking and error handling.
3
4
## Capabilities
5
6
### ConfigView Class
7
8
Base class for configuration queries that provides dictionary-like access with validation and type conversion capabilities.
9
10
```python { .api }
11
class ConfigView:
12
def get(self, template=REQUIRED):
13
"""
14
Get configuration value with optional validation template.
15
16
Parameters:
17
- template: Type or Template object for validation/conversion
18
19
Returns:
20
Validated and converted configuration value
21
22
Raises:
23
- NotFoundError: If value is missing and required
24
- ConfigTypeError: If value doesn't match expected type
25
- ConfigValueError: If value is invalid
26
"""
27
28
def exists(self):
29
"""
30
Check if this configuration key exists in any source.
31
32
Returns:
33
bool: True if key exists, False otherwise
34
"""
35
36
def first(self):
37
"""
38
Get the first available value and its source.
39
40
Returns:
41
tuple: (value, source) pair
42
43
Raises:
44
- NotFoundError: If no value is found
45
"""
46
47
def keys(self):
48
"""
49
Get all available keys from all sources for this view.
50
51
Returns:
52
list: Available configuration keys
53
54
Raises:
55
- ConfigTypeError: If this view is not a dictionary
56
"""
57
58
def items(self):
59
"""
60
Get key-value pairs as (key, subview) tuples.
61
62
Returns:
63
list: Tuples of (key, ConfigView) pairs
64
"""
65
66
def values(self):
67
"""
68
Get all values as ConfigView objects.
69
70
Returns:
71
list: ConfigView objects for each value
72
"""
73
74
def sequence(self):
75
"""
76
Iterate over this view as a list.
77
78
Returns:
79
generator: ConfigView objects for each list item
80
81
Raises:
82
- ConfigTypeError: If this view is not a list
83
"""
84
85
def set(self, value):
86
"""
87
Override this configuration value with highest priority.
88
89
Parameters:
90
- value: New configuration value
91
"""
92
93
def add(self, value):
94
"""
95
Add a default value with lowest priority.
96
97
Parameters:
98
- value: Default configuration value
99
"""
100
101
def set_args(self, namespace, dots=False):
102
"""
103
Overlay parsed command-line arguments onto configuration.
104
105
Parameters:
106
- namespace: argparse.Namespace or dict with argument values
107
- dots (bool): Split keys on dots to create nested structure
108
"""
109
110
def all_contents(self):
111
"""
112
Get all values from all sources for this view.
113
114
Returns:
115
generator: (value, source) tuples for all matching values
116
"""
117
118
def flatten(self, redact=False):
119
"""
120
Generate flat dictionary representation of configuration.
121
122
Parameters:
123
- redact (bool): Replace sensitive values with redaction placeholder
124
125
Returns:
126
dict: Flattened configuration with dot-separated keys
127
"""
128
129
def set_redaction(self, path, flag):
130
"""
131
Mark a configuration path as sensitive for redaction.
132
133
Parameters:
134
- path (str): Configuration path (e.g., 'database.password')
135
- flag (bool): Whether to redact this path
136
"""
137
138
def get_redactions(self):
139
"""
140
Get dictionary of redaction flags for configuration paths.
141
142
Returns:
143
dict: Mapping of paths to redaction flags
144
"""
145
146
def resolve(self):
147
"""
148
Generate all (value, source) pairs for this view from all sources.
149
150
Returns:
151
generator: (value, ConfigSource) tuples in priority order
152
"""
153
154
def root(self):
155
"""
156
Get the root ConfigView for this view hierarchy.
157
158
Returns:
159
RootView: Root view containing all configuration sources
160
"""
161
162
def __iter__(self):
163
"""
164
Iterate over configuration keys or sequence items.
165
166
Returns:
167
generator: Keys for mappings or ConfigView objects for sequences
168
"""
169
170
def __contains__(self, key):
171
"""
172
Check if key exists in configuration.
173
174
Parameters:
175
- key: Key to check for existence
176
177
Returns:
178
bool: True if key exists in any source
179
"""
180
181
def __getitem__(self, key):
182
"""
183
Access nested configuration via subscript notation.
184
185
Parameters:
186
- key: Dictionary key or list index
187
188
Returns:
189
Subview: ConfigView for the nested configuration item
190
"""
191
192
def __setitem__(self, key, value):
193
"""
194
Set nested configuration value via subscript notation.
195
196
Parameters:
197
- key: Dictionary key or list index
198
- value: Value to set
199
"""
200
201
def __str__(self):
202
"""
203
Get string representation of configuration value.
204
205
Returns:
206
str: String representation of the first available value
207
"""
208
209
def __bool__(self):
210
"""
211
Check if this configuration view has any values.
212
213
Returns:
214
bool: True if any sources contain values for this view
215
"""
216
```
217
218
### Type Conversion Methods
219
220
Convenience methods for common type conversions with built-in validation.
221
222
```python { .api }
223
class ConfigView:
224
def as_str(self):
225
"""
226
Get value as string.
227
228
Returns:
229
str: String representation of value
230
"""
231
232
def as_str_expanded(self):
233
"""
234
Get value as string with environment variable expansion.
235
236
Returns:
237
str: String with $VAR and ${VAR} expanded
238
"""
239
240
def as_filename(self):
241
"""
242
Get value as validated filename with path resolution.
243
244
Returns:
245
str: Absolute path to file
246
"""
247
248
def as_path(self):
249
"""
250
Get value as pathlib.Path object.
251
252
Returns:
253
pathlib.Path: Path object for the file
254
"""
255
256
def as_number(self):
257
"""
258
Get value as numeric type (int or float).
259
260
Returns:
261
int or float: Numeric value
262
"""
263
264
def as_choice(self, choices):
265
"""
266
Get value validated against list of choices.
267
268
Parameters:
269
- choices: Sequence of valid values or Enum class
270
271
Returns:
272
Validated choice value
273
"""
274
275
def as_str_seq(self, split=True):
276
"""
277
Get value as list of strings.
278
279
Parameters:
280
- split (bool): Split single strings on whitespace
281
282
Returns:
283
list: List of string values
284
"""
285
286
def as_pairs(self, default_value=None):
287
"""
288
Get value as list of key-value pairs.
289
290
Parameters:
291
- default_value: Default value for keys without explicit values
292
293
Returns:
294
list: List of (key, value) tuples
295
"""
296
```
297
298
### Subview Access
299
300
Accessing nested configuration data through subscript notation and attribute-style access.
301
302
```python { .api }
303
class Subview(ConfigView):
304
def __init__(self, parent, key):
305
"""
306
Create a subview for accessing nested configuration data.
307
308
Parameters:
309
- parent (ConfigView): Parent view object
310
- key: Dictionary key or list index for access
311
"""
312
```
313
314
## Usage Examples
315
316
### Basic Value Access
317
318
```python
319
import confuse
320
321
config = confuse.Configuration('myapp')
322
323
# Dictionary-style access
324
database_host = config['database']['host'].get(str)
325
port = config['database']['port'].get(int)
326
327
# Check if key exists
328
if config['debug'].exists():
329
debug_mode = config['debug'].get(bool)
330
331
# Get with default using template
332
timeout = config['timeout'].get(confuse.Number(30.0))
333
```
334
335
### Type Conversion
336
337
```python
338
import confuse
339
340
config = confuse.Configuration('myapp')
341
342
# Basic type conversions
343
name = config['app_name'].as_str()
344
count = config['worker_count'].as_number()
345
config_file = config['config_path'].as_filename()
346
output_dir = config['output_dir'].as_path()
347
348
# String expansion with environment variables
349
expanded_path = config['data_path'].as_str_expanded() # Expands $HOME/data
350
351
# Choice validation
352
log_level = config['log_level'].as_choice(['DEBUG', 'INFO', 'WARNING', 'ERROR'])
353
354
# List of strings
355
plugins = config['plugins'].as_str_seq() # ['plugin1', 'plugin2']
356
keywords = config['keywords'].as_str_seq(split=True) # 'foo bar' -> ['foo', 'bar']
357
```
358
359
### Dictionary and List Access
360
361
```python
362
import confuse
363
364
config = confuse.Configuration('myapp')
365
366
# Iterate over dictionary keys
367
for key in config['servers']:
368
server_config = config['servers'][key]
369
print(f"Server {key}: {server_config['host'].as_str()}")
370
371
# Get all keys and values
372
server_keys = config['servers'].keys()
373
server_views = config['servers'].values()
374
375
# Iterate over list items
376
for server_view in config['server_list'].sequence():
377
hostname = server_view['hostname'].as_str()
378
port = server_view['port'].as_number()
379
print(f"Server: {hostname}:{port}")
380
381
# List iteration with index access
382
servers = config['servers']
383
for i, server_view in enumerate(servers):
384
print(f"Server {i}: {server_view.get(str)}")
385
```
386
387
### Command-Line Integration
388
389
```python
390
import confuse
391
import argparse
392
393
config = confuse.Configuration('myapp')
394
395
# Parse command-line arguments
396
parser = argparse.ArgumentParser()
397
parser.add_argument('--host', default='localhost')
398
parser.add_argument('--port', type=int, default=8080)
399
parser.add_argument('--database-url', dest='database.url')
400
parser.add_argument('--verbose', action='store_true')
401
402
args = parser.parse_args()
403
404
# Overlay arguments onto configuration
405
config.set_args(args, dots=True) # Split 'database.url' into nested structure
406
407
# Access merged configuration
408
host = config['host'].as_str() # From args or config file
409
port = config['port'].as_number() # From args or config file
410
db_url = config['database']['url'].as_str() # From --database-url
411
```
412
413
### Error Handling
414
415
```python
416
import confuse
417
418
config = confuse.Configuration('myapp')
419
420
try:
421
# This will raise NotFoundError if 'required_setting' is missing
422
value = config['required_setting'].get(str)
423
except confuse.NotFoundError:
424
print("Required setting is missing from configuration")
425
426
try:
427
# This will raise ConfigTypeError if value is not an integer
428
count = config['item_count'].get(int)
429
except confuse.ConfigTypeError as e:
430
print(f"Invalid type for item_count: {e}")
431
432
try:
433
# This will raise ConfigValueError for invalid values
434
level = config['log_level'].as_choice(['DEBUG', 'INFO', 'WARNING', 'ERROR'])
435
except confuse.ConfigValueError as e:
436
print(f"Invalid log level: {e}")
437
```
438
439
### Complex Data Structures
440
441
```python
442
import confuse
443
444
config = confuse.Configuration('myapp')
445
446
# Working with nested dictionaries
447
database_config = config['database']
448
if database_config.exists():
449
# Get individual values
450
host = database_config['host'].as_str()
451
port = database_config['port'].as_number()
452
ssl_enabled = database_config['ssl'].get(bool)
453
454
# Check for optional nested values
455
if database_config['connection_pool'].exists():
456
max_connections = database_config['connection_pool']['max_size'].get(int)
457
458
# Working with lists of dictionaries
459
for server in config['servers'].sequence():
460
hostname = server['hostname'].as_str()
461
options = server['options'].as_str_seq()
462
print(f"Server {hostname} with options: {options}")
463
464
# Key-value pair processing
465
pairs = config['environment'].as_pairs()
466
for key, value in pairs:
467
print(f"Environment: {key}={value}")
468
```
469
470
### View State and Manipulation
471
472
```python
473
import confuse
474
475
config = confuse.Configuration('myapp')
476
477
# Set values at runtime
478
config['debug'] = True
479
config.set({'logging': {'level': 'DEBUG', 'format': 'detailed'}})
480
481
# Add default values (lowest priority)
482
config.add({'timeout': 30, 'retries': 3})
483
484
# Set nested values
485
config['database']['host'] = 'production.db.example.com'
486
487
# Check current configuration state
488
all_keys = list(config.keys())
489
has_database = 'database' in config
490
database_exists = config['database'].exists()
491
```
492
493
### Redaction and Sensitive Data
494
495
```python
496
import confuse
497
498
config = confuse.Configuration('myapp')
499
config.set({'database': {'password': 'secret123', 'host': 'localhost'}})
500
501
# Mark sensitive paths for redaction
502
config.set_redaction('database.password', True)
503
config.set_redaction('api_key', True)
504
505
# Get flat configuration with redaction
506
flat_config = config.flatten(redact=True)
507
print(flat_config) # {'database.password': 'REDACTED', 'database.host': 'localhost'}
508
509
# Get redaction settings
510
redactions = config.get_redactions()
511
print(redactions) # {'database.password': True, 'api_key': True}
512
513
# Iterate over all configuration values and sources
514
for value, source in config.all_contents():
515
print(f"Value: {value}, Source: {source.filename}")
516
```