Skip to main content

ConfigParser Override

Version Build Status

ConfigParserOverride enhances the python standard library built-in ConfigParser by allowing you to override or add new options using; environment variables and directly assigned key-value arguments.

NOTE: This package only depends on the Python Standard Library!

Features

  • Override configuration options with environment variables.
  • Override configuration options with directly assigned arguments.
  • Convert configuration object to a dataclass and cast the values to predefined datatypes.
  • Find and collect configuration files in conventional locations based on your operating system.

Install

pip install configparser-override

Usage

Example of how to use ConfigParserOverride:

Example config.ini File

[DEFAULT]
default_key1 = default_value1
default_key2 = default_value2

[section1]
key1 = value1
key2 = value2

[section2]
key3 = value3
key4 = value4

Python Code

import os

from configparser_override import ConfigParserOverride

# Optionally set environment variables for overriding
os.environ["MYAPP_DEFAULT_KEY1"] = "overridden_default_value1"
os.environ["MYAPP_SECTION1__KEY1"] = "overridden_value1"
os.environ["MYAPP_SECTION2__KEY3"] = "overridden_value3"

# Initialize the parser with an optional environment variable prefix and
# overrides from direct assignments.
parser = ConfigParserOverride(
    env_prefix="MYAPP_",
    # Sections & options are case insensitive by default
    SECTION2__KEY4="direct_override_value4",
    section2__key5="direct_override_value5",
)

# Read configuration from a file
parser.read(filenames="config.ini")

# Apply overrides
parser.apply_overrides()

# Access the configuration
print(config.defaults()["default_key1"])  # Output: overridden_default_value1
print(config.defaults()["default_key2"])  # Output: default_value2
print(config["section1"]["key1"])  # Output: overridden_value1
print(config["section1"]["key2"])  # Output: value2
print(config["section2"]["key3"])  # Output: overridden_value3
print(config["section2"]["key4"])  # Output: direct_override_value4
print(config["section2"]["key5"])  # Output: direct_override_value5

Configuration source precedence

Configuration options can be overridden in three ways. This is the order of precedence:

  1. Directly assigned arguments during initialization of the ConfigParserOverride class.
  2. Environment variables.
  3. Configuration files.

Environment variable configuration

To override configuration options, use environment variables with the following format. Separate sections and options using double underscores (__):

  • With Prefix (MYAPP_ as an example):

    • For DEFAULT section: [PREFIX][OPTION]
    • For other sections: [PREFIX][SECTION]__[OPTION]
  • No Prefix:

    • For DEFAULT section: [OPTION]
    • For other sections: [SECTION]__[OPTION]

Example:

  • To override key1 in section1 with prefix MYAPP_, use MYAPP_SECTION1__KEY1.

Find and collect configuration files

The library also contains a helper function config_file_collector that will search for configuration files in conventional locations based on your OS. The collected files can then be used as input to ConfigParserOverride.read()

Searched paths

Linux and MacOS

Unix systems follows XDG base directory specification and used environment variables:

  • XDG_CONFIG_HOME (User config)
    • Default to $HOME/.config
  • XDG_CONFIG_DIRS (System wide config)
    • List of directories separated by semicolon :
    • Default to /etc/xdg

Windows

Windows paths are specific in environment variables:

  • APPDATA (User config)
    • Usually: C:\Users\USERNAME\AppData\Roaming
  • PROGRAMDATA (System wide config)
    • Usually: C:\ProgramData

Example

from configparser_override import ConfigParserOverride, config_file_collector

collected_files = config_file_collector(file_name="config.ini", app_name="myapp")

print(collected_files)
# For Linux and MacOS
# Output: ["/etc/xdg/myapp/config.ini", "/home/USERNAME/.config/myapp/config.ini"]

# For Windows
# Output: ["C:/ProgramData/myapp/config.ini", "C:/Users/USERNAME/AppData/Roaming/myapp/config.ini"]

parser = ConfigParserOverride()
parser.read(filenames=collected_files)
parser.apply_overrides()
config = parser.config

Convert to a Dataclass and Validate Data Types

The library features a ConfigConverter class, which enables the conversion of configuration data into a dataclass instance. This functionality is particularly useful for ensuring that the configuration adheres to the expected format, since it tries to cast the option in the config to the types in the dataclass. Hence, it also allows you to take advantage of various typing frameworks and tools, such as integrations with your text editor, providing enhanced validation and code assistance.

Example

from dataclasses import dataclass
from typing import Optional

from configparser_override import ConfigParserOverride


@dataclass
class Section1:
    key1: int
    key2: list[str]
    key3: Optional[str] = None


@dataclass
class ExampleConfig:
    section1: Section1


# Initialize the parser with overrides
parser = ConfigParserOverride(
    section1__key1="42", section1__key2="['item1', 'item2']"
)

# Read configuration from **optional** file
parser.read(filenames=[])

# Apply overrides
parser.apply_overrides()

# Convert to dataclass
config_as_dataclass = parser.to_dataclass(ExampleConfig)

print(config_as_dataclass.section1.key1)  # Output: 42
print(type(config_as_dataclass.section1.key1))  # Output: <class 'int'>
print(config_as_dataclass.section1.key2)  # Output: ['item1', 'item2']
print(type(config_as_dataclass.section1.key2))  # Output: <class 'list'>
print(config_as_dataclass.section1.key3)  # Output: None

Data Types

Supported data types are:

  • String
  • Integer
  • Bool
  • Float
  • Complex
  • Bytes
  • pathlib.Path

Collections (nesting is supported):

  • List
  • Dict
  • Set
  • Tuple

Others:

  • None
  • Optional | Option does not need to exist in config
  • Union | Tries to cast until successful, in the order the types are specified
  • Any | no type cast

Built-in custom types:

  • SecretType (abstract): Custom abstract type that masks the secret value when converted to a string. Use SecretType.get_secret_value() to retrieve the actual value.
    • SecretStr | Implementation for strings
    • SecretBytes | Implementation for bytes

Experimental Support for Arbitrary Types:

The converter offers an experimental option to accept any object that can be initialized with a single, unnamed string argument. To enable this feature, set allow_custom_types = True when using the converter (the default is False).

For example, a compatible object initialization might look like this: MyCustomType("string value from config").

Platform Dependency

Different operating systems handle environment variables differently. Linux is case sensitive while Windows is not. See os.environ docs. Hence, it is safest to always use capitalized environment variables to avoid any unexpected behavior.

Recommendation

In order to avoid any unanticipated issues and make your code safe to run on any platform, follow these rules:

Element Recommended Case
Environment variables UPPERCASE
Environment variable prefix UPPERCASE
DEFAULT section in config.ini (as per convention in the standard library ConfigParser) UPPERCASE
Sections in config.ini files lowercase
Options in config.ini files lowercase
Directly assigned arguments lowercase

Case Sensitivity Handling

By default, ConfigParserOverride tries to stores everything as lowercase, with the exception of Section headers that are read from configuration files, where the existing casing in the file is honored. However, if you want to override such a section with an environment variable or direct assignment, it will recognize the existing casing of the section and continue to use that even though you use other casing in the override method.

It is highly discouraged, but you can make ConfigParserOverride case-sensitive by initializing it with the argument case_sensitive_overrides=True.

from configparser_override import ConfigParserOverride

parser = ConfigParserOverride(env_prefix="MYAPP_", case_sensitive_overrides=True)

Release files for configparser-override 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for configparser-override 0.11.0
File Size Uploaded
configparser_override-0.11.0.tar.gz 27.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for configparser-override 0.11.0
File Interpreter ABI Platform
configparser_override-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.0 kB

Release files / configparser_override-0.11.0.tar.gz

Download URL configparser_override-0.11.0.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ae8521170780af5f12589df94db2665cf00277b13b381e13ae01955dea378503
BLAKE2b-256 checksum
How to use checksums
aec04e0f326c717847b8e7156a24fd702427d866d8be69f2fce306a3eb696bd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2024.

Transparency log

Release files / configparser_override-0.11.0-py3-none-any.whl

Download URL configparser_override-0.11.0-py3-none-any.whl
Size 18.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f963503c92613e7dacb810f21d67bf2f567fb32f3d6f41c76541bc37b85bc033
BLAKE2b-256 checksum
How to use checksums
317e499df998845f7a63d6e6a2aceb35e924b5343b45bf23600d94df7867695d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2024.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.0 This release

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page