Updated configparser from stdlib for earlier Pythons with enhanced configuration file parsing capabilities.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Abstract base class defining the interpolation interface for value substitution.
class Interpolation:
"""
Abstract base class for interpolation implementations.
Provides the interface for value substitution in configuration files.
Subclasses must implement before_get, before_set, and before_write methods.
"""
def before_get(self, parser, section, option, value, defaults): ...
def before_set(self, parser, section, option, value): ...
def before_write(self, parser, section, option, value): ...Standard %(name)s style interpolation compatible with Python's standard library configparser.
class BasicInterpolation(Interpolation):
"""
Basic interpolation using %(name)s syntax.
Supports:
- %(option)s - references option in same section
- %(section:option)s - references option in different section
- %% - literal % character
Interpolation depth limited by MAX_INTERPOLATION_DEPTH (default: 10).
Raises:
- InterpolationMissingOptionError: referenced option doesn't exist
- InterpolationSyntaxError: malformed interpolation syntax
- InterpolationDepthError: recursion too deep
"""Advanced ${section:option} style interpolation with additional features.
class ExtendedInterpolation(Interpolation):
"""
Extended interpolation using ${section:option} syntax.
Supports:
- ${option} - references option in same section
- ${section:option} - references option in different section
- $$ - literal $ character
More flexible than BasicInterpolation with cleaner syntax
and better error handling.
Raises:
- InterpolationMissingOptionError: referenced option doesn't exist
- InterpolationSyntaxError: malformed interpolation syntax
- InterpolationDepthError: recursion too deep
"""from backports import configparser
# BasicInterpolation is the default
config = configparser.ConfigParser()
config.read_string('''
[DEFAULT]
home_dir = /home/user
log_level = INFO
[application]
config_file = %(home_dir)s/.myapp/config.ini
log_file = %(home_dir)s/.myapp/app.log
debug = %(log_level)s
[database]
data_dir = %(home_dir)s/data
backup_dir = %(data_dir)s/backups
''')
# Values are interpolated automatically
config_file = config.get('application', 'config_file')
# Result: '/home/user/.myapp/config.ini'
backup_dir = config.get('database', 'backup_dir')
# Result: '/home/user/data/backups'from backports import configparser
config = configparser.ConfigParser(
interpolation=configparser.ExtendedInterpolation()
)
config.read_string('''
[DEFAULT]
base_path = /opt/myapp
version = 2.1
[server]
host = localhost
port = 8080
url = http://${host}:${port}
[paths]
config = ${DEFAULT:base_path}/config
logs = ${DEFAULT:base_path}/logs/v${DEFAULT:version}
data = ${config}/data
[database]
connection = sqlite:///${paths:data}/app.db
''')
# Extended interpolation with cleaner syntax
server_url = config.get('server', 'url')
# Result: 'http://localhost:8080'
db_connection = config.get('database', 'connection')
# Result: 'sqlite:////opt/myapp/config/data/app.db'from backports import configparser
# Use RawConfigParser to disable interpolation entirely
raw_config = configparser.RawConfigParser()
raw_config.read_string('''
[section]
literal_percent = This has %(not_interpolated)s text
literal_dollar = This has ${not_interpolated} text
''')
# Values are returned as-is
literal = raw_config.get('section', 'literal_percent')
# Result: 'This has %(not_interpolated)s text'
# Or disable for specific get() calls
config = configparser.ConfigParser()
config.read_string('''
[section]
value = %(interpolated)s
''')
# Get raw value without interpolation
raw_value = config.get('section', 'value', raw=True)
# Result: '%(interpolated)s'from backports import configparser
config = configparser.ConfigParser()
config.read_string('''
[database]
host = db.example.com
port = 5432
name = myapp
[api]
db_url = postgresql://%(database:host)s:%(database:port)s/%(database:name)s
[backup]
db_host = %(database:host)s
backup_path = /backups/%(database:name)s
''')
# Cross-section interpolation
db_url = config.get('api', 'db_url')
# Result: 'postgresql://db.example.com:5432/myapp'
backup_path = config.get('backup', 'backup_path')
# Result: '/backups/myapp'from backports import configparser
config = configparser.ConfigParser()
config.read_string('''
[paths]
config = %(base)s/config
logs = %(base)s/logs
data = %(base)s/data
''')
# Provide additional variables for interpolation
custom_vars = {'base': '/opt/myapp', 'env': 'production'}
config_path = config.get('paths', 'config', vars=custom_vars)
# Result: '/opt/myapp/config'
logs_path = config.get('paths', 'logs', vars=custom_vars)
# Result: '/opt/myapp/logs'from backports import configparser
config = configparser.ConfigParser()
config.read_string('''
[section]
valid = %(existing)s
invalid_missing = %(nonexistent)s
invalid_syntax = %(incomplete
recursive_a = %(recursive_b)s
recursive_b = %(recursive_a)s
existing = hello
''')
try:
# This works
value = config.get('section', 'valid') # 'hello'
# Missing reference
config.get('section', 'invalid_missing')
except configparser.InterpolationMissingOptionError as e:
print(f"Missing option: {e}")
try:
# Syntax error
config.get('section', 'invalid_syntax')
except configparser.InterpolationSyntaxError as e:
print(f"Syntax error: {e}")
try:
# Recursion too deep
config.get('section', 'recursive_a')
except configparser.InterpolationDepthError as e:
print(f"Recursion error: {e}")from backports import configparser
# Basic interpolation - escape % with %%
config_basic = configparser.ConfigParser()
config_basic.read_string('''
[section]
percent_literal = This is 100%% complete
percent_var = This uses %(variable)s interpolation
variable = actual_value
''')
literal = config_basic.get('section', 'percent_literal')
# Result: 'This is 100% complete'
# Extended interpolation - escape $ with $$
config_ext = configparser.ConfigParser(
interpolation=configparser.ExtendedInterpolation()
)
config_ext.read_string('''
[section]
dollar_literal = This costs $$50
dollar_var = This uses ${variable} interpolation
variable = actual_value
''')
literal = config_ext.get('section', 'dollar_literal')
# Result: 'This costs $50'Install with Tessl CLI
npx tessl i tessl/pypi-configparser