Skip to main content

Configuration library for Python 🔧 Load from multiple sources

Project description

ilexconf

Configuration Library 🔧 for Python

Build Status Coverage Status License: MIT PyPI Code style: black

Quick Start

Install

$ pip install ilexconf

Populate ilexconf with values

Config object is initialized using arbitrary number of Mapping objects and keyword arguments. It can even be empty.

When we initialize config all the values are merged. Last Mapping is merged on top of the previous mapping values. And keyword arguments override even that.

For a settings file settings.json with the following content ...

{
    "database": {
        "connection": {
            "host": "localhost",
            "port": 5432
        }
    }
}

The code below will produce a merged Config with merged values:

from ilexconf import Config, from_json

# Create configuration using JSON file, dictionary and key-value pair
config = Config(
    from_json("settings.json"),
    { "database": { "connection": { "host": "test.local" } } },
    database__connection__port=4000
)

# Check it was created and values are merged properly
assert config.as_dict() == {
    "database": {
        "connection": {
            "host": "test.local",
            "port": 4000
        }
    }
}

Access values however you like

You can access any key in the hierarchical structure using classical Python dict notation, dotted keys, attributes, or any combination of this methods.

# Classic way
assert config["database"]["conection"]["host"] == "test.local"

# Dotted key
assert config["database.connection.host"] == "test.local"

# Attributes
assert config.database.connection.host == "test.local"

# Any combination of the above
assert config["database"].connection.host == "test.local"
assert config.database["connection.host"] == "test.local"
assert config.database["connection"].host == "test.local"
assert config.database.connection["host"] == "test.local"

Change existing values and create new ones

Similarly, you can set values of any key (even if the don't exist in the Config) using all of the ways above.

Notice, contrary to what you would expect from the Python dictionaries, setting nested keys that do not exist is allowed.

# Classic way
config["database"]["connection"]["port"] = 8080
assert config["database"]["connection"]["port"] == 8080

# Dotted key (that does not exist yet)
config["database.connection.user"] = "root"
assert config["database.connection.user"] == "root"

# Attributes (also does not exist yet)
config.database.connection.password = "secret stuff"
assert config.database.connection.password == "secret stuff"

Update with another Mapping object

If you just assign a value to any key, you override any previous value of that key.

In order to merge assigned value with the existing one, use merge method.

config.database.connection.merge({ "password": "different secret" })
assert config.database.connection.password == "different secret"

Represent as dictionary

For any purposes you might find fit you can convert entire structure of the Config object into dictionary, which will be returned to you as essentially a deep copy of the object.

assert config.as_dict() == {
    "database": {
        "connection": {
            "host": "test.local",
            "port": 8080,
            "user": "root",
            "password": "different secret"
        }
    }
}

Save to file

You can serialize the file as json any time using the write method.

# Write updated config back as JSON file
config.write("settings.json")

WARNING: This might throw a serialization error if any of the values contained in the Config are custom objects that cannot be converted to str. Also, obviously, you might not be able to correctly parse an object back, if it's saved to JSON as MyObject(<function MyObject.__init__.<locals>.<lambda> at 0x108927af0>, {}) or something.

Subclass

Subclassing Config class is very convenient for implementation of your own config classes with custom logic.

Consider this example:

import ilexconf

class Config(ilexconf.Config):
    """
    Your custom Configuration class
    """

    def __init__(do_stuff=False):
        # Initialize your custom config with JSON by default
        super().__init__(self, ilexconf.from_json("setting.json"))

        # Add some custom value depending on some logic
        if do_stuff:
            self.my.custom.key = "Yes, do stuff"

        self.merge({
            "Horizon": "Up"
        })

# Now you can use your custom Configuration everywhere
config = Config(do_stuff=True)
assert config.my.custom.key == "Yes, do stuff"
assert config.Horizon == "Up"

Internals

Under the hood ilexconf is implemented as a defaultdict where every key with Mapping value is represented as another Config object. This creates a hierarchy of Config objects.

Alternatives

Below is a primitive analysis of features of alternative libraries doing similar job.

Library ilexconf dynaconf python-configuration
Read from .json x x x
Read from .toml x x x
Read from .ini x x x
Read from env vars x x x
Read from .py x x
Read from .env x
Read from dict object x x
Read from Redis x
Read from Hashicorp Vault x
Default values x x
Multienvironment x
Attribute access x x x
Dotted key access x x x
Merging x x x
Interpolation x x
Saving x x
CLI x x
Printing x x
Validators x
Masking sensitive info x x
Django integration x
Flask integration x
Hot reload
Python 3.6 x
Python 3.7 x
Python 3.8 x x

Kudos

ilexconf heavily borrows from python-configuration library and is inspired by it.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ilexconf-0.6.8.tar.gz (6.8 kB view details)

Uploaded Source

Built Distribution

ilexconf-0.6.8-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file ilexconf-0.6.8.tar.gz.

File metadata

  • Download URL: ilexconf-0.6.8.tar.gz
  • Upload date:
  • Size: 6.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.0rc1 CPython/3.8.0 Linux/4.15.0-1077-gcp

File hashes

Hashes for ilexconf-0.6.8.tar.gz
Algorithm Hash digest
SHA256 7b5e18c3f3b61aa8e4217b5526f80b99c8b2e9291fe5abea639c2e5fa234b3b8
MD5 bb51c7e4c6c6880559923c6712d9fdbd
BLAKE2b-256 bc9e1a4912d8cf1aa840419fa952362473a6c1cda8a1dde22fddf29fa6107824

See more details on using hashes here.

File details

Details for the file ilexconf-0.6.8-py3-none-any.whl.

File metadata

  • Download URL: ilexconf-0.6.8-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.0rc1 CPython/3.8.0 Linux/4.15.0-1077-gcp

File hashes

Hashes for ilexconf-0.6.8-py3-none-any.whl
Algorithm Hash digest
SHA256 57521a3af94a39fae9c1a13e1d74751be5cf2caf1ee0838d4e2c47c3f5c68a3f
MD5 1d2ac06fb5982bd8e5ff78e084de6f3e
BLAKE2b-256 afc0ce4e6a339b441d38ea19e7ebb9b3a883835efedf8f62dbcff4c63127f104

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page