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
Comprehensive exception hierarchy for handling various configuration parsing and access errors. The configparser library provides specific exceptions for different error conditions to enable precise error handling.
Root exception class for all configparser-related errors.
class Error(Exception):
"""
Base class for all configparser exceptions.
All other configparser exceptions inherit from this base class,
allowing for comprehensive error catching.
"""Exceptions related to section operations and validation.
class NoSectionError(Error):
"""
Raised when a specified section is not found.
Attributes:
- section: str, the name of the missing section
"""
class DuplicateSectionError(Error):
"""
Raised when attempting to add a section that already exists.
Occurs when strict=True and a duplicate section is encountered.
Attributes:
- section: str, the name of the duplicate section
- source: str, the source where duplication occurred
- lineno: int, line number where duplication occurred
"""Exceptions related to option operations and validation.
class NoOptionError(Error):
"""
Raised when a specified option is not found in a section.
Attributes:
- option: str, the name of the missing option
- section: str, the name of the section
"""
class DuplicateOptionError(Error):
"""
Raised when attempting to add an option that already exists.
Occurs when strict=True and a duplicate option is encountered.
Attributes:
- option: str, the name of the duplicate option
- section: str, the name of the section
- source: str, the source where duplication occurred
- lineno: int, line number where duplication occurred
"""Exceptions related to value interpolation and substitution.
class InterpolationError(Error):
"""
Base class for interpolation-related errors.
Attributes:
- option: str, the option being interpolated
- section: str, the section containing the option
"""
class InterpolationMissingOptionError(InterpolationError):
"""
Raised when interpolation references a non-existent option.
Attributes:
- option: str, the option being interpolated
- section: str, the section containing the option
- rawval: str, the raw value containing the bad reference
- reference: str, the missing option reference
"""
class InterpolationSyntaxError(InterpolationError):
"""
Raised when interpolation syntax is malformed.
Attributes:
- option: str, the option being interpolated
- section: str, the section containing the option
- msg: str, description of the syntax error
"""
class InterpolationDepthError(InterpolationError):
"""
Raised when interpolation recursion exceeds maximum depth.
Attributes:
- option: str, the option being interpolated
- section: str, the section containing the option
- rawval: str, the raw value causing deep recursion
"""Exceptions related to configuration file parsing.
class ParsingError(Error):
"""
Raised when configuration file parsing fails.
Can contain multiple individual parsing errors from a single source.
Attributes:
- source: str, the source being parsed (filename, '<string>', etc.)
- errors: list of tuple, (filename, lineno, line) for each error
"""
class MissingSectionHeaderError(ParsingError):
"""
Raised when an option appears before any section header.
Attributes:
- source: str, the source being parsed
- lineno: int, line number of the problematic line
- line: str, the content of the problematic line
"""
class MultilineContinuationError(ParsingError):
"""
Raised when multiline value continuation is malformed.
Attributes:
- source: str, the source being parsed
- lineno: int, line number of the problematic line
- line: str, the content of the problematic line
"""Additional exceptions for specific error conditions.
class UnnamedSectionDisabledError(Error):
"""
Raised when options without section are encountered but disabled.
Occurs when allow_unnamed_section=False and options appear
before any section header.
"""
class InvalidWriteError(Error):
"""
Raised when write operation cannot be completed.
Typically occurs when configuration state is invalid for writing.
"""from backports import configparser
config = configparser.ConfigParser()
try:
config.read('config.ini')
value = config.get('database', 'host')
except configparser.NoSectionError:
print("Database section not found")
config.add_section('database')
config.set('database', 'host', 'localhost')
except configparser.NoOptionError:
print("Host option not found in database section")
config.set('database', 'host', 'localhost')from backports import configparser
config = configparser.ConfigParser(strict=True)
try:
config.read_string('''
[section1]
option1 = value1
[section1] # Duplicate section
option2 = value2
''')
except configparser.DuplicateSectionError as e:
print(f"Duplicate section '{e.section}' at line {e.lineno}")
print(f"Source: {e.source}")
try:
config.read_string('''
[section]
option = value
option = another_value # Duplicate option
''')
except configparser.DuplicateOptionError as e:
print(f"Duplicate option '{e.option}' in section '{e.section}'")
print(f"At line {e.lineno} in {e.source}")from backports import configparser
config = configparser.ConfigParser()
config.read_string('''
[section]
valid_option = hello
broken_reference = %(missing_option)s
syntax_error = %(incomplete_reference
recursive_a = %(recursive_b)s
recursive_b = %(recursive_a)s
''')
# Handle missing reference
try:
value = config.get('section', 'broken_reference')
except configparser.InterpolationMissingOptionError as e:
print(f"Missing option '{e.reference}' referenced in '{e.option}'")
print(f"Raw value: {e.rawval}")
# Handle syntax error
try:
value = config.get('section', 'syntax_error')
except configparser.InterpolationSyntaxError as e:
print(f"Syntax error in '{e.option}': {e.msg}")
# Handle recursion depth
try:
value = config.get('section', 'recursive_a')
except configparser.InterpolationDepthError as e:
print(f"Recursion too deep in '{e.option}'")
print(f"Raw value: {e.rawval}")from backports import configparser
config = configparser.ConfigParser()
try:
config.read_string('''
option_without_section = value # Error: no section header
[section]
valid_option = value
''')
except configparser.MissingSectionHeaderError as e:
print(f"Missing section header at line {e.lineno}")
print(f"Problematic line: {e.line}")
# Handle multiple parsing errors
malformed_config = '''
option1 = value1 # No section header
[section
option2 = value2 # Missing closing bracket
invalid line without equals
'''
try:
config.read_string(malformed_config)
except configparser.ParsingError as e:
print(f"Parsing failed for {e.source}")
for filename, lineno, line in e.errors:
print(f" Line {lineno}: {line}")from backports import configparser
def safe_config_read(filename):
"""Safely read configuration with comprehensive error handling."""
config = configparser.ConfigParser()
try:
files_read = config.read(filename)
if not files_read:
print(f"Warning: Configuration file {filename} not found")
return None
except configparser.ParsingError as e:
print(f"Failed to parse {e.source}:")
for source, lineno, line in e.errors:
print(f" Line {lineno}: {line.strip()}")
return None
except Exception as e:
print(f"Unexpected error reading configuration: {e}")
return None
return config
def safe_get_value(config, section, option, converter=None, fallback=None):
"""Safely get configuration value with error handling."""
try:
if converter:
return converter(config.get(section, option))
return config.get(section, option)
except configparser.NoSectionError:
print(f"Section '{section}' not found")
return fallback
except configparser.NoOptionError:
print(f"Option '{option}' not found in section '{section}'")
return fallback
except (configparser.InterpolationError, ValueError) as e:
print(f"Error processing '{section}.{option}': {e}")
return fallback
# Usage
config = safe_config_read('app.ini')
if config:
host = safe_get_value(config, 'database', 'host', fallback='localhost')
port = safe_get_value(config, 'database', 'port', int, fallback=5432)
debug = safe_get_value(config, 'app', 'debug',
lambda x: x.lower() == 'true', fallback=False)from backports import configparser
config = configparser.ConfigParser()
# Catch all configparser exceptions
try:
config.read('config.ini')
value = config.get('section', 'option')
except configparser.Error as e:
print(f"ConfigParser error: {e}")
# Handle any configparser-specific error
# Catch specific interpolation errors
try:
value = config.get('section', 'interpolated_option')
except configparser.InterpolationError as e:
print(f"Interpolation error: {e}")
# Handle any interpolation-related errorInstall with Tessl CLI
npx tessl i tessl/pypi-configparser