0
# Configuration System
1
2
Foliant's configuration system provides flexible YAML-based project configuration with extensible tag support for includes, path resolution, and environment variables. The modular parser architecture allows custom configuration features through plugin extensions.
3
4
## Capabilities
5
6
### Main Configuration Parser
7
8
Dynamic parser class that inherits from all available configuration parsers, providing unified access to all configuration features.
9
10
```python { .api }
11
class Parser(*get_available_config_parsers().values()):
12
"""
13
Main configuration parser that combines all available parsers.
14
Provides unified interface for parsing foliant.yml files.
15
"""
16
```
17
18
### Base Configuration Parser
19
20
Foundation class for all configuration parsers providing core YAML parsing functionality.
21
22
```python { .api }
23
class BaseParser:
24
"""Base configuration parser with core YAML functionality."""
25
26
_defaults = {
27
'src_dir': Path('./src'),
28
'tmp_dir': Path('./__folianttmp__')
29
}
30
31
def __init__(self, project_path: Path, config_file_name: str,
32
logger: Logger, quiet: bool = False):
33
"""
34
Initialize configuration parser.
35
36
Parameters:
37
- project_path (Path): Path to project directory
38
- config_file_name (str): Name of configuration file
39
- logger (Logger): Logger instance for parsing messages
40
- quiet (bool): Suppress parsing output
41
"""
42
43
def parse(self) -> dict:
44
"""
45
Parse configuration file into Python dictionary.
46
Applies defaults and converts paths to Path objects.
47
48
Returns:
49
dict: Parsed configuration with defaults applied
50
51
Raises:
52
FileNotFoundError: If configuration file not found
53
yaml.YAMLError: If YAML parsing fails
54
"""
55
```
56
57
### Include Parser
58
59
Handles `!include` YAML tags for including external configuration files or sections.
60
61
```python { .api }
62
class Parser(BaseParser):
63
"""Parser for !include YAML tags."""
64
65
def _resolve_include_tag(self, _, node) -> str | dict:
66
"""
67
Replace !include tag with content from referenced file.
68
69
Supports two formats:
70
- !include file.yml (includes entire file)
71
- !include file.yml#section (includes specific section)
72
73
Parameters:
74
- _ (unused): YAML loader parameter
75
- node: YAML node containing include path
76
77
Returns:
78
str | dict: Content from included file
79
80
Raises:
81
ValueError: If include syntax has more than one # separator
82
FileNotFoundError: If included file not found
83
"""
84
85
def __init__(self, *args, **kwargs):
86
"""
87
Initialize include parser and register !include constructor.
88
89
Parameters:
90
- *args: Arguments passed to BaseParser
91
- **kwargs: Keyword arguments passed to BaseParser
92
"""
93
```
94
95
### Path Parser
96
97
Handles path-related YAML tags for flexible path resolution relative to project directory.
98
99
```python { .api }
100
class Parser(BaseParser):
101
"""Parser for path-related YAML tags."""
102
103
def _resolve_path_tag(self, _, node) -> str:
104
"""
105
Convert !path tag to absolute POSIX path.
106
Relative paths are resolved relative to project directory.
107
108
Parameters:
109
- _ (unused): YAML loader parameter
110
- node: YAML node containing path value
111
112
Returns:
113
str: Absolute POSIX path
114
115
Raises:
116
FileNotFoundError: If path does not exist (strict=True)
117
"""
118
119
def _resolve_project_path_tag(self, _, node) -> Path:
120
"""
121
Convert !project_path tag to absolute path relative to project.
122
Does not check for file existence.
123
124
Parameters:
125
- _ (unused): YAML loader parameter
126
- node: YAML node containing path value
127
128
Returns:
129
Path: Absolute path object
130
"""
131
132
@staticmethod
133
def _resolve_rel_path_tag(_, node) -> Path:
134
"""
135
Convert !rel_path tag to Path object without resolution.
136
137
Parameters:
138
- _ (unused): YAML loader parameter
139
- node: YAML node containing path value
140
141
Returns:
142
Path: Path object from node value
143
"""
144
145
def __init__(self, *args, **kwargs):
146
"""
147
Initialize path parser and register path-related constructors.
148
149
Parameters:
150
- *args: Arguments passed to BaseParser
151
- **kwargs: Keyword arguments passed to BaseParser
152
"""
153
```
154
155
### Environment Variable Parser
156
157
Handles `!env` YAML tags for including environment variable values in configuration.
158
159
```python { .api }
160
class Parser(BaseParser):
161
"""Parser for !env YAML tags."""
162
163
@staticmethod
164
def _resolve_env_tag(_, node) -> str | int | bool | dict | list | None:
165
"""
166
Replace !env tag with environment variable value.
167
168
Parameters:
169
- _ (unused): YAML loader parameter
170
- node: YAML node containing environment variable name
171
172
Returns:
173
Any: Environment variable value parsed as YAML, or None if not found
174
"""
175
176
def __init__(self, *args, **kwargs):
177
"""
178
Initialize environment parser and register !env constructor.
179
180
Parameters:
181
- *args: Arguments passed to BaseParser
182
- **kwargs: Keyword arguments passed to BaseParser
183
"""
184
```
185
186
## Usage Examples
187
188
### Basic Configuration Parsing
189
190
```python
191
from foliant.config import Parser
192
from pathlib import Path
193
import logging
194
195
# Set up logger
196
logger = logging.getLogger('foliant')
197
198
# Parse configuration
199
parser = Parser(
200
project_path=Path('./my-project'),
201
config_file_name='foliant.yml',
202
logger=logger,
203
quiet=False
204
)
205
206
config = parser.parse()
207
print(f"Source directory: {config['src_dir']}")
208
print(f"Temp directory: {config['tmp_dir']}")
209
print(f"Project title: {config.get('title', 'Untitled')}")
210
```
211
212
### Configuration with Include Tags
213
214
Example `foliant.yml`:
215
```yaml
216
title: My Documentation
217
chapters:
218
- !include chapters.yml
219
preprocessors:
220
- !include config/preprocessors.yml#development
221
```
222
223
Example usage:
224
```python
225
from foliant.config import Parser
226
from pathlib import Path
227
import logging
228
229
parser = Parser(Path('.'), 'foliant.yml', logging.getLogger())
230
config = parser.parse()
231
232
# chapters.yml and preprocessors.yml content is merged
233
print(config['chapters'])
234
print(config['preprocessors'])
235
```
236
237
### Configuration with Path Tags
238
239
Example `foliant.yml`:
240
```yaml
241
title: Documentation
242
src_dir: !path ./sources
243
custom_path: !project_path ./assets/images
244
relative_path: !rel_path ./templates
245
```
246
247
Example usage:
248
```python
249
config = parser.parse()
250
251
# Paths are resolved appropriately
252
print(config['src_dir']) # Absolute path to ./sources
253
print(config['custom_path']) # Absolute path to ./assets/images
254
print(config['relative_path']) # Path object for ./templates
255
```
256
257
### Configuration with Environment Variables
258
259
Example `foliant.yml`:
260
```yaml
261
title: !env PROJECT_TITLE
262
debug: !env DEBUG_MODE
263
api_key: !env API_KEY
264
```
265
266
Example usage:
267
```python
268
import os
269
270
# Set environment variables
271
os.environ['PROJECT_TITLE'] = 'My Project'
272
os.environ['DEBUG_MODE'] = 'true'
273
os.environ['API_KEY'] = 'secret123'
274
275
config = parser.parse()
276
print(config['title']) # 'My Project'
277
print(config['debug']) # True (parsed as YAML boolean)
278
print(config['api_key']) # 'secret123'
279
```
280
281
### Custom Configuration Parser
282
283
```python
284
from foliant.config.base import BaseParser
285
from yaml import add_constructor
286
287
class CustomParser(BaseParser):
288
"""Custom parser with additional YAML tags."""
289
290
def _resolve_custom_tag(self, _, node):
291
"""Handle custom !mytag syntax."""
292
return f"processed: {node.value}"
293
294
def __init__(self, *args, **kwargs):
295
super().__init__(*args, **kwargs)
296
add_constructor('!mytag', self._resolve_custom_tag)
297
298
# Use custom parser
299
parser = CustomParser(Path('.'), 'foliant.yml', logger)
300
config = parser.parse()
301
```
302
303
## Configuration File Structure
304
305
Default configuration structure:
306
```yaml
307
# Required
308
title: Project Title
309
310
# Optional with defaults
311
src_dir: ./src # Source directory
312
tmp_dir: ./__folianttmp__ # Temporary build directory
313
314
# Backend configuration
315
backend_config:
316
mkdocs:
317
theme: material
318
pandoc:
319
template: custom.tex
320
321
# Preprocessors
322
preprocessors:
323
- includes
324
- plantuml:
325
format: png
326
327
# Custom settings
328
chapters:
329
- index.md
330
- guide.md
331
```