Imperfect
Imperfect is a Python library (version 0.4.0) designed for editing `configparser`-compatible INI files while preserving comments and whitespace. It operates by parsing configuration files into a Concrete Syntax Tree (CST) of nodes, allowing programmatic modifications that maintain the original file's structural integrity. The library is under active development with irregular releases.
Common errors
-
KeyError: 'section_name' or unexpected behavior with casing of section/option names.
cause `imperfect` aims for `RawConfigParser` compatibility, which defaults to case-sensitive section and option names. If you are accustomed to `configparser.ConfigParser` (which is case-insensitive by default), this can lead to lookup failures or incorrect behavior.fixAlways refer to section and option names with their exact casing as present in the INI file. If migrating from `configparser.ConfigParser` where `optionxform = str` was not explicitly set, be mindful of casing. -
Modified configuration file loses comments, custom spacing, or has unexpected formatting after writing back.
cause Attempting to manipulate the configuration content as a plain string, or mixing `imperfect`'s CST-based editing with direct string operations or standard `configparser` methods that do not preserve comments and whitespace.fixEnsure all modifications are performed using the `imperfect.ConfigFile` object's methods (e.g., `set_value`, direct manipulation of `ConfigEntry` objects within sections). Always use `conf.text` or `conf.build(file_object)` to retrieve or write the modified content to ensure CST-based preservation.
Warnings
- gotcha Imperfect aims for compatibility with `configparser.RawConfigParser`, which includes replicating some of its longstanding 'odd behaviors' or bugs. Developers should be aware that certain quirks of `configparser` might be preserved rather than 'fixed'.
- gotcha While `imperfect` is designed to preserve whitespace and comments, precise control over their exact placement when inserting or deleting entries can be complex. Direct manipulation of `ConfigEntry` objects might be required for fine-grained control.
- gotcha Version 0.4.0 introduced support for parsing unnamed sections. If previous application logic relied on older `imperfect` versions to reject (or not parse) configuration files containing unnamed sections, this change could alter behavior. Such files will now be processed.
Install
-
pip install imperfect
Imports
- ConfigFile
from imperfect import ConfigFile
- parse_string
from imperfect import parse_string
Quickstart
import imperfect
import io
# Simulate an existing config file content
initial_config_content = '''
[metadata]
# the package name
name = imperfect
# slurp the readme
long_description = file: README.md
[options]
packages = imperfect
'''
# Parse the string content into an imperfect.ConfigFile object
conf: imperfect.ConfigFile = imperfect.parse_string(initial_config_content)
# Set a new value, it will be added at the end of the section by default
conf.set_value("metadata", "long_description_content_type", "text/markdown")
# Print the modified content, preserving comments and whitespace
print(conf.text)