0
# Interpolation
1
2
Value substitution capabilities that allow dynamic configuration values to reference other options within the same configuration. Interpolation enables flexible configuration setups with reusable values and computed settings.
3
4
## Capabilities
5
6
### Interpolation Base Class
7
8
Abstract base class defining the interpolation interface for value substitution.
9
10
```python { .api }
11
class Interpolation:
12
"""
13
Abstract base class for interpolation implementations.
14
15
Provides the interface for value substitution in configuration files.
16
Subclasses must implement before_get, before_set, and before_write methods.
17
"""
18
19
def before_get(self, parser, section, option, value, defaults): ...
20
def before_set(self, parser, section, option, value): ...
21
def before_write(self, parser, section, option, value): ...
22
```
23
24
### BasicInterpolation
25
26
Standard %(name)s style interpolation compatible with Python's standard library configparser.
27
28
```python { .api }
29
class BasicInterpolation(Interpolation):
30
"""
31
Basic interpolation using %(name)s syntax.
32
33
Supports:
34
- %(option)s - references option in same section
35
- %(section:option)s - references option in different section
36
- %% - literal % character
37
38
Interpolation depth limited by MAX_INTERPOLATION_DEPTH (default: 10).
39
40
Raises:
41
- InterpolationMissingOptionError: referenced option doesn't exist
42
- InterpolationSyntaxError: malformed interpolation syntax
43
- InterpolationDepthError: recursion too deep
44
"""
45
```
46
47
### ExtendedInterpolation
48
49
Advanced ${section:option} style interpolation with additional features.
50
51
```python { .api }
52
class ExtendedInterpolation(Interpolation):
53
"""
54
Extended interpolation using ${section:option} syntax.
55
56
Supports:
57
- ${option} - references option in same section
58
- ${section:option} - references option in different section
59
- $$ - literal $ character
60
61
More flexible than BasicInterpolation with cleaner syntax
62
and better error handling.
63
64
Raises:
65
- InterpolationMissingOptionError: referenced option doesn't exist
66
- InterpolationSyntaxError: malformed interpolation syntax
67
- InterpolationDepthError: recursion too deep
68
"""
69
```
70
71
## Usage Examples
72
73
### Basic Interpolation Usage
74
75
```python
76
from backports import configparser
77
78
# BasicInterpolation is the default
79
config = configparser.ConfigParser()
80
81
config.read_string('''
82
[DEFAULT]
83
home_dir = /home/user
84
log_level = INFO
85
86
[application]
87
config_file = %(home_dir)s/.myapp/config.ini
88
log_file = %(home_dir)s/.myapp/app.log
89
debug = %(log_level)s
90
91
[database]
92
data_dir = %(home_dir)s/data
93
backup_dir = %(data_dir)s/backups
94
''')
95
96
# Values are interpolated automatically
97
config_file = config.get('application', 'config_file')
98
# Result: '/home/user/.myapp/config.ini'
99
100
backup_dir = config.get('database', 'backup_dir')
101
# Result: '/home/user/data/backups'
102
```
103
104
### Extended Interpolation Usage
105
106
```python
107
from backports import configparser
108
109
config = configparser.ConfigParser(
110
interpolation=configparser.ExtendedInterpolation()
111
)
112
113
config.read_string('''
114
[DEFAULT]
115
base_path = /opt/myapp
116
version = 2.1
117
118
[server]
119
host = localhost
120
port = 8080
121
url = http://${host}:${port}
122
123
[paths]
124
config = ${DEFAULT:base_path}/config
125
logs = ${DEFAULT:base_path}/logs/v${DEFAULT:version}
126
data = ${config}/data
127
128
[database]
129
connection = sqlite:///${paths:data}/app.db
130
''')
131
132
# Extended interpolation with cleaner syntax
133
server_url = config.get('server', 'url')
134
# Result: 'http://localhost:8080'
135
136
db_connection = config.get('database', 'connection')
137
# Result: 'sqlite:////opt/myapp/config/data/app.db'
138
```
139
140
### Disabling Interpolation
141
142
```python
143
from backports import configparser
144
145
# Use RawConfigParser to disable interpolation entirely
146
raw_config = configparser.RawConfigParser()
147
148
raw_config.read_string('''
149
[section]
150
literal_percent = This has %(not_interpolated)s text
151
literal_dollar = This has ${not_interpolated} text
152
''')
153
154
# Values are returned as-is
155
literal = raw_config.get('section', 'literal_percent')
156
# Result: 'This has %(not_interpolated)s text'
157
158
# Or disable for specific get() calls
159
config = configparser.ConfigParser()
160
config.read_string('''
161
[section]
162
value = %(interpolated)s
163
''')
164
165
# Get raw value without interpolation
166
raw_value = config.get('section', 'value', raw=True)
167
# Result: '%(interpolated)s'
168
```
169
170
### Cross-Section References
171
172
```python
173
from backports import configparser
174
175
config = configparser.ConfigParser()
176
177
config.read_string('''
178
[database]
179
host = db.example.com
180
port = 5432
181
name = myapp
182
183
[api]
184
db_url = postgresql://%(database:host)s:%(database:port)s/%(database:name)s
185
186
[backup]
187
db_host = %(database:host)s
188
backup_path = /backups/%(database:name)s
189
''')
190
191
# Cross-section interpolation
192
db_url = config.get('api', 'db_url')
193
# Result: 'postgresql://db.example.com:5432/myapp'
194
195
backup_path = config.get('backup', 'backup_path')
196
# Result: '/backups/myapp'
197
```
198
199
### Custom Variables in Interpolation
200
201
```python
202
from backports import configparser
203
204
config = configparser.ConfigParser()
205
206
config.read_string('''
207
[paths]
208
config = %(base)s/config
209
logs = %(base)s/logs
210
data = %(base)s/data
211
''')
212
213
# Provide additional variables for interpolation
214
custom_vars = {'base': '/opt/myapp', 'env': 'production'}
215
216
config_path = config.get('paths', 'config', vars=custom_vars)
217
# Result: '/opt/myapp/config'
218
219
logs_path = config.get('paths', 'logs', vars=custom_vars)
220
# Result: '/opt/myapp/logs'
221
```
222
223
### Error Handling
224
225
```python
226
from backports import configparser
227
228
config = configparser.ConfigParser()
229
230
config.read_string('''
231
[section]
232
valid = %(existing)s
233
invalid_missing = %(nonexistent)s
234
invalid_syntax = %(incomplete
235
recursive_a = %(recursive_b)s
236
recursive_b = %(recursive_a)s
237
existing = hello
238
''')
239
240
try:
241
# This works
242
value = config.get('section', 'valid') # 'hello'
243
244
# Missing reference
245
config.get('section', 'invalid_missing')
246
except configparser.InterpolationMissingOptionError as e:
247
print(f"Missing option: {e}")
248
249
try:
250
# Syntax error
251
config.get('section', 'invalid_syntax')
252
except configparser.InterpolationSyntaxError as e:
253
print(f"Syntax error: {e}")
254
255
try:
256
# Recursion too deep
257
config.get('section', 'recursive_a')
258
except configparser.InterpolationDepthError as e:
259
print(f"Recursion error: {e}")
260
```
261
262
### Literal Percent and Dollar Signs
263
264
```python
265
from backports import configparser
266
267
# Basic interpolation - escape % with %%
268
config_basic = configparser.ConfigParser()
269
config_basic.read_string('''
270
[section]
271
percent_literal = This is 100%% complete
272
percent_var = This uses %(variable)s interpolation
273
variable = actual_value
274
''')
275
276
literal = config_basic.get('section', 'percent_literal')
277
# Result: 'This is 100% complete'
278
279
# Extended interpolation - escape $ with $$
280
config_ext = configparser.ConfigParser(
281
interpolation=configparser.ExtendedInterpolation()
282
)
283
config_ext.read_string('''
284
[section]
285
dollar_literal = This costs $$50
286
dollar_var = This uses ${variable} interpolation
287
variable = actual_value
288
''')
289
290
literal = config_ext.get('section', 'dollar_literal')
291
# Result: 'This costs $50'
292
```