0
# Configuration Management
1
2
Hierarchical configuration system with lazy loading, environment variable support, and file-based persistence. Manages application settings, project configuration, and plugin configuration.
3
4
## Capabilities
5
6
### Configuration File Management
7
8
File-based configuration management with support for reading, writing, validation, and default configuration restoration.
9
10
```python { .api }
11
class ConfigFile:
12
"""
13
Configuration file manager for hatch settings.
14
15
Handles reading, writing, and managing the hatch configuration file
16
with support for default configuration restoration and validation.
17
"""
18
19
def __init__(self, path: Path | None = None):
20
"""
21
Initialize configuration file manager.
22
23
Args:
24
path (Path, optional): Path to configuration file.
25
If None, uses default location.
26
"""
27
28
@property
29
def path(self) -> Path:
30
"""
31
Path to the configuration file.
32
33
Returns:
34
Path object pointing to configuration file
35
"""
36
37
def save(self, content: str | None = None) -> None:
38
"""
39
Save configuration content to file.
40
41
Args:
42
content (str, optional): Configuration content to save.
43
If None, saves current configuration.
44
"""
45
46
def load(self) -> dict:
47
"""
48
Load configuration from file.
49
50
Returns:
51
Dict containing configuration data
52
53
Raises:
54
OSError: If file cannot be read
55
"""
56
57
def read(self) -> str:
58
"""
59
Read raw configuration file content.
60
61
Returns:
62
Raw configuration file content as string
63
"""
64
65
def read_scrubbed(self) -> str:
66
"""
67
Read configuration content with sensitive data removed.
68
69
Removes passwords, tokens, and other sensitive information
70
for safe display or logging.
71
72
Returns:
73
Scrubbed configuration content
74
"""
75
76
def restore(self) -> None:
77
"""
78
Restore default configuration.
79
80
Creates a new configuration file with default settings,
81
overwriting any existing configuration.
82
"""
83
84
@classmethod
85
def get_default_location(cls) -> Path:
86
"""
87
Get default configuration file location.
88
89
Returns:
90
Path to default configuration file location
91
"""
92
```
93
94
### Root Configuration
95
96
Main configuration object providing access to all hatch settings with lazy loading and validation.
97
98
```python { .api }
99
class RootConfig:
100
"""
101
Root configuration object with lazy field parsing.
102
103
Provides access to all hatch configuration sections including
104
directories, projects, publishing, templates, and terminal settings.
105
"""
106
107
@property
108
def mode(self) -> str:
109
"""
110
Configuration mode determining project resolution behavior.
111
112
Values:
113
- 'aware': Use configured project if no local project found
114
- 'local': Always use current directory
115
- 'project': Always use configured project
116
117
Returns:
118
Configuration mode string
119
"""
120
121
@property
122
def project(self) -> str | None:
123
"""
124
Default project name for project and aware modes.
125
126
Returns:
127
Project name or None if not configured
128
"""
129
130
@property
131
def shell(self) -> str:
132
"""
133
Default shell for environment activation and commands.
134
135
Returns:
136
Shell name or path
137
"""
138
139
@property
140
def dirs(self):
141
"""
142
Directory configuration for data and cache locations.
143
144
Returns:
145
DirectoryConfig object with data and cache directory paths
146
"""
147
148
@property
149
def projects(self) -> dict[str, str]:
150
"""
151
Configured projects mapping names to paths.
152
153
Returns:
154
Dict mapping project names to directory paths
155
"""
156
157
@property
158
def publish(self):
159
"""
160
Publishing configuration for package indices and authentication.
161
162
Returns:
163
PublishConfig object with index and authentication settings
164
"""
165
166
@property
167
def template(self):
168
"""
169
Template configuration for project initialization.
170
171
Returns:
172
TemplateConfig object with template settings and defaults
173
"""
174
175
@property
176
def terminal(self):
177
"""
178
Terminal configuration for output formatting and styles.
179
180
Returns:
181
TerminalConfig object with styling and display settings
182
"""
183
```
184
185
### Directory Configuration
186
187
Configuration for data storage, cache, and temporary file locations with platform-appropriate defaults.
188
189
```python { .api }
190
class DirectoryConfig:
191
"""Configuration for hatch directories."""
192
193
@property
194
def data(self) -> str:
195
"""
196
Data directory for persistent hatch data.
197
198
Returns:
199
Path to data directory
200
"""
201
202
@property
203
def cache(self) -> str:
204
"""
205
Cache directory for temporary and cached data.
206
207
Returns:
208
Path to cache directory
209
"""
210
211
def expand_path(self, path: str) -> Path:
212
"""
213
Expand path with environment variables and user home.
214
215
Args:
216
path (str): Path to expand
217
218
Returns:
219
Expanded Path object
220
"""
221
```
222
223
### Publishing Configuration
224
225
Configuration for package publishing including index URLs, authentication, and publishing options.
226
227
```python { .api }
228
class PublishConfig:
229
"""Configuration for package publishing."""
230
231
@property
232
def index(self) -> str:
233
"""
234
Default package index URL.
235
236
Returns:
237
Package index URL (defaults to PyPI)
238
"""
239
240
@property
241
def username(self) -> str | None:
242
"""
243
Default username for package index authentication.
244
245
Returns:
246
Username or None if not configured
247
"""
248
249
@property
250
def repositories(self) -> dict[str, dict]:
251
"""
252
Configured package repositories.
253
254
Returns:
255
Dict mapping repository names to configuration dicts
256
"""
257
258
def get_repository_config(self, name: str) -> dict:
259
"""
260
Get configuration for named repository.
261
262
Args:
263
name (str): Repository name
264
265
Returns:
266
Repository configuration dict
267
"""
268
```
269
270
### Template Configuration
271
272
Configuration for project templates including default values and template-specific settings.
273
274
```python { .api }
275
class TemplateConfig:
276
"""Configuration for project templates."""
277
278
@property
279
def name(self) -> str:
280
"""
281
Default template name for project creation.
282
283
Returns:
284
Template name
285
"""
286
287
@property
288
def author(self) -> str | None:
289
"""
290
Default author name for new projects.
291
292
Returns:
293
Author name or None if not configured
294
"""
295
296
@property
297
def email(self) -> str | None:
298
"""
299
Default author email for new projects.
300
301
Returns:
302
Author email or None if not configured
303
"""
304
305
@property
306
def license(self) -> str:
307
"""
308
Default license for new projects.
309
310
Returns:
311
License identifier (defaults to 'MIT')
312
"""
313
314
@property
315
def plugins(self) -> dict[str, dict]:
316
"""
317
Template plugin configurations.
318
319
Returns:
320
Dict mapping template plugin names to configurations
321
"""
322
```
323
324
### Terminal Configuration
325
326
Configuration for terminal output including colors, styles, and formatting options.
327
328
```python { .api }
329
class TerminalConfig:
330
"""Configuration for terminal output."""
331
332
@property
333
def styles(self):
334
"""
335
Terminal styling configuration.
336
337
Returns:
338
StyleConfig object with color and formatting settings
339
"""
340
341
@property
342
def shell(self) -> str:
343
"""
344
Preferred shell for terminal operations.
345
346
Returns:
347
Shell name or path
348
"""
349
```
350
351
### Environment Variable Support
352
353
Configuration system integration with environment variables for overriding settings and providing defaults.
354
355
```python { .api }
356
class AppEnvVars:
357
"""Application environment variable names."""
358
359
ENV: str = 'HATCH_ENV' # Default environment name
360
ENV_ACTIVE: str = 'HATCH_ENV_ACTIVE' # Currently active environment
361
QUIET: str = 'HATCH_QUIET' # Quiet mode setting
362
VERBOSE: str = 'HATCH_VERBOSE' # Verbose mode setting
363
INTERACTIVE: str = 'HATCH_INTERACTIVE' # Interactive mode setting
364
PYTHON: str = 'HATCH_PYTHON' # Python executable path
365
NO_COLOR: str = 'NO_COLOR' # Disable colored output
366
FORCE_COLOR: str = 'FORCE_COLOR' # Force colored output
367
368
class ConfigEnvVars:
369
"""Configuration environment variable names."""
370
371
PROJECT: str = 'HATCH_PROJECT' # Project name override
372
DATA: str = 'HATCH_DATA_DIR' # Data directory path
373
CACHE: str = 'HATCH_CACHE_DIR' # Cache directory path
374
CONFIG: str = 'HATCH_CONFIG' # Configuration file path
375
376
class PublishEnvVars:
377
"""Publishing environment variable names."""
378
379
USER: str = 'HATCH_INDEX_USER' # Package index username
380
AUTH: str = 'HATCH_INDEX_AUTH' # Package index authentication
381
REPO: str = 'HATCH_INDEX_REPO' # Package index repository URL
382
CA_CERT: str = 'HATCH_INDEX_CA_CERT' # CA certificate path
383
CLIENT_CERT: str = 'HATCH_INDEX_CLIENT_CERT' # Client certificate path
384
CLIENT_KEY: str = 'HATCH_INDEX_CLIENT_KEY' # Client key path
385
```
386
387
### Configuration Validation
388
389
Utilities for validating configuration structure, values, and consistency across different configuration sections.
390
391
```python { .api }
392
def validate_config(config: dict) -> list[str]:
393
"""
394
Validate configuration structure and values.
395
396
Args:
397
config (dict): Configuration to validate
398
399
Returns:
400
List of validation errors (empty if valid)
401
"""
402
403
def validate_directory_config(dirs: dict) -> list[str]:
404
"""
405
Validate directory configuration.
406
407
Args:
408
dirs (dict): Directory configuration section
409
410
Returns:
411
List of validation errors
412
"""
413
414
def validate_publish_config(publish: dict) -> list[str]:
415
"""
416
Validate publishing configuration.
417
418
Args:
419
publish (dict): Publishing configuration section
420
421
Returns:
422
List of validation errors
423
"""
424
425
def validate_project_references(config: dict) -> list[str]:
426
"""
427
Validate project references in configuration.
428
429
Args:
430
config (dict): Full configuration
431
432
Returns:
433
List of validation errors for project references
434
"""
435
```
436
437
### Configuration Utilities
438
439
Helper functions for configuration management including merging, path resolution, and default value handling.
440
441
```python { .api }
442
def merge_configs(base: dict, override: dict) -> dict:
443
"""
444
Merge configuration dictionaries with override precedence.
445
446
Args:
447
base (dict): Base configuration
448
override (dict): Override configuration
449
450
Returns:
451
Merged configuration dict
452
"""
453
454
def resolve_config_path(path: str, config_dir: Path) -> Path:
455
"""
456
Resolve configuration path relative to config directory.
457
458
Args:
459
path (str): Path to resolve (may be relative or absolute)
460
config_dir (Path): Configuration directory for relative paths
461
462
Returns:
463
Resolved absolute Path
464
"""
465
466
def get_default_config() -> dict:
467
"""
468
Get default configuration structure.
469
470
Returns:
471
Dict with default configuration values
472
"""
473
474
def expand_env_vars(config: dict) -> dict:
475
"""
476
Expand environment variables in configuration values.
477
478
Args:
479
config (dict): Configuration with potential env var references
480
481
Returns:
482
Configuration with expanded environment variables
483
"""
484
```
485
486
## Usage Examples
487
488
### Basic Configuration Management
489
490
```python
491
from hatch.config.user import ConfigFile
492
from hatch.config.model import RootConfig
493
494
# Load configuration
495
config_file = ConfigFile()
496
config_data = config_file.load()
497
config = RootConfig(config_data)
498
499
# Access configuration values
500
print(f"Mode: {config.mode}")
501
print(f"Data directory: {config.dirs.data}")
502
print(f"Cache directory: {config.dirs.cache}")
503
504
# Access project configuration
505
if config.project:
506
print(f"Default project: {config.project}")
507
508
# Access publishing configuration
509
print(f"Default index: {config.publish.index}")
510
repositories = config.publish.repositories
511
for name, repo_config in repositories.items():
512
print(f"Repository {name}: {repo_config.get('url')}")
513
```
514
515
### Configuration File Operations
516
517
```python
518
from hatch.config.user import ConfigFile
519
from pathlib import Path
520
521
# Create config file manager
522
config_file = ConfigFile()
523
524
# Check if config exists
525
if not config_file.path.exists():
526
print("Creating default configuration...")
527
config_file.restore()
528
529
# Read configuration
530
config_data = config_file.load()
531
print(f"Loaded config from: {config_file.path}")
532
533
# Read scrubbed version (safe for logging)
534
scrubbed_content = config_file.read_scrubbed()
535
print("Scrubbed configuration:")
536
print(scrubbed_content)
537
538
# Custom config file location
539
custom_config = ConfigFile(Path("./custom-config.toml"))
540
if custom_config.path.exists():
541
custom_data = custom_config.load()
542
```
543
544
### Environment Variable Integration
545
546
```python
547
from hatch.config.constants import AppEnvVars, ConfigEnvVars
548
import os
549
550
# Set environment variables
551
os.environ[AppEnvVars.VERBOSE] = '2'
552
os.environ[AppEnvVars.ENV] = 'test'
553
os.environ[ConfigEnvVars.DATA] = '/custom/data/path'
554
555
# Configuration will automatically use these values
556
config_file = ConfigFile()
557
config_data = config_file.load()
558
config = RootConfig(config_data)
559
560
# Environment variables override configuration file values
561
print(f"Data directory: {config.dirs.data}") # Uses env var value
562
```
563
564
### Configuration Validation
565
566
```python
567
from hatch.config import validate_config, validate_publish_config
568
569
# Validate full configuration
570
config_data = config_file.load()
571
errors = validate_config(config_data)
572
if errors:
573
print("Configuration errors:")
574
for error in errors:
575
print(f" - {error}")
576
577
# Validate specific sections
578
publish_config = config_data.get('publish', {})
579
publish_errors = validate_publish_config(publish_config)
580
if publish_errors:
581
print("Publishing configuration errors:")
582
for error in publish_errors:
583
print(f" - {error}")
584
```
585
586
### Custom Configuration Creation
587
588
```python
589
from hatch.config.user import ConfigFile
590
from hatch.config import get_default_config, merge_configs
591
592
# Start with default configuration
593
config_data = get_default_config()
594
595
# Add custom settings
596
custom_settings = {
597
'mode': 'project',
598
'project': 'my-main-project',
599
'dirs': {
600
'data': '~/.local/share/hatch',
601
'cache': '~/.cache/hatch'
602
},
603
'publish': {
604
'index': 'https://my-private-index.com/simple/',
605
'username': 'myuser'
606
},
607
'template': {
608
'author': 'My Name',
609
'email': 'my@email.com',
610
'license': 'Apache-2.0'
611
}
612
}
613
614
# Merge configurations
615
final_config = merge_configs(config_data, custom_settings)
616
617
# Save configuration
618
config_file = ConfigFile()
619
import toml
620
config_file.save(toml.dumps(final_config))
621
```
622
623
### Project-Specific Configuration
624
625
```python
626
from hatch.config.model import RootConfig
627
628
# Configuration with project-specific settings
629
config_data = {
630
'mode': 'aware',
631
'projects': {
632
'web-app': '/path/to/web-app',
633
'api-service': '/path/to/api-service',
634
'shared-lib': '/path/to/shared-lib'
635
},
636
'project': 'web-app' # Default project
637
}
638
639
config = RootConfig(config_data)
640
641
# Access project paths
642
projects = config.projects
643
for name, path in projects.items():
644
print(f"Project {name}: {path}")
645
646
# Get default project
647
default_project = config.project
648
print(f"Default project: {default_project}")
649
```