Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

python-simpleconf

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

python-simpleconf

Simple configuration management with python.

pipPyPI
Version
0.9.3
Maintainers
1

simpleconf

Simple configuration management for python

Installation

# released version
pip install python-simpleconf

# Install support for ini
pip install python-simpleconf[ini]

# Install support for dotenv
pip install python-simpleconf[dotenv]

# Install support for yaml
pip install python-simpleconf[yaml]

# Install support for toml
pip install python-simpleconf[toml]

# Install support for all supported formats
pip install python-simpleconf[all]

Features

  • Multiple formats supported
  • Type casting
  • Profile support
  • Simple APIs
  • Async loading support
  • Templated configuration files support (jinja2 and liquid)

Usage

Loading configurations

import asyncio
from simpleconf import Config


async def main():
  # Load a single file
  conf = Config.load('~/xxx.ini')
  # load multiple files, later files override previous ones
  conf = Config.load(
    '~/xxx.ini', '~/xxx.env', '~/xxx.yaml', '~/xxx.toml',
    '~/xxx.json', 'simpleconf.osenv', {'a': 3}
  )

  # Load a single file with a different loader
  conf = Config.load('~/xxx.ini', loader="toml")

  # Async loading
  conf = await Config.a_load('~/xxx.ini')

if __name__ == "__main__":
  asyncio.run(main())

Accessing configuration values

from simpleconf import Config

conf = Config.load({'a': 1, 'b': {'c': 2}})
# conf.a == 1
# conf.b.c == 2

Supported formats

  • .ini/.cfg/.config (parsed by iniconfig).
    • For confiurations without profiles, an ini-like configuration like must have a default (case-insensitive) section.
  • .env (using python-dotenv). A file with environment variables.
  • .yaml/.yml (using pyyaml). A file with YAML data.
  • .toml (using rtoml). A file with TOML data.
  • .json (using json). A file with JSON data.
  • XXX.osenv: System environment variables with prefix XXX_ (case-sensitive) is used.
    • XXX_A=1 will be loaded as conf.A = 1.
  • python dictionary.
  • Strings format of the above formats are also supported.
    • "{'a': 1}" will be loaded as conf.a = 1.

Profile support

Loading configurations

Loading dictionaries
from simpleconf import ProfileConfig

conf = ProfileConfig.load({'default': {'a': 1})
# conf.a == 1

# Asynchronous loading
# conf = await ProfileConfig.a_load({'default': {'a': 1})
# conf.a == 1
Loading a .env file

config.env

# config.env
default_a=1
from simpleconf import ProfileConfig

conf = ProfileConfig.load('config.env')
# conf.a == 1
Loading ini-like configuration files
# config.ini
[default]
a = 1
from simpleconf import ProfileConfig

conf = ProfileConfig.load('config.ini')
# conf.a == 1
Loading JSON files

config.json

{
  "default": {
    "a": 1
  }
}
from simpleconf import ProfileConfig

conf = ProfileConfig.load('config.json')
# conf.a == 1
Loading system environment variables
from os import environ
from simpleconf import ProfileConfig

environ['XXX_DEFAULT_A'] = '1'

conf = ProfileConfig.load('XXX.osenv')
# conf.a == 1
Loading TOML files
# config.toml
[default]
a = 1
from simpleconf import ProfileConfig

conf = ProfileConfig.load('config.toml')
# conf.a == 1
Loading YAML files
# config.yaml
default:
  a: 1
from simpleconf import ProfileConfig

conf = ProfileConfig.load('config.yaml')
# conf.a == 1

Switching profile

from simpleconf import ProfileConfig

conf = ProfileConfig.load(
   {'default': {'a': 1, 'b': 2}, 'dev': {'a': 3}, 'prod': {'a': 4}}
)
# conf.a == 1; conf.b == 2
# ProfileConfig.profiles(conf) == ['default', 'dev', 'prod']
# ProfileConfig.pool(conf) == {'default': {'a': 1, 'b': 2}, 'dev': {'a': 3}, 'prod': {'a': 4}}
# ProfileConfig.current_profile(conf) == 'default'
# ProfileConfig.base_profile(conf) == 'default'

ProfileConfig.use_profile(conf, 'dev')
# conf.a == 3; conf.b == 2
# ProfileConfig.current_profile(conf) == 'dev'
# ProfileConfig.base_profile(conf) == 'default'

# use a different base profile
ProfileConfig.use_profile(conf, 'prod', base='dev')
# conf.a == 4   # No 'b' in conf
# ProfileConfig.current_profile(conf) == 'prod'
# ProfileConfig.base_profile(conf) == 'dev'

# Copy configuration instead of inplace modification
conf2 = ProfileConfig.use_profile(conf, 'dev', copy=True)
# conf2 is not conf
# conf2.a == 3; conf2.b == 2

# Use a context manager
with ProfileConfig.use_profile(conf2, 'default'):
    conf2.a == 3
    conf2.b == 2
# conf2.a == 3; conf2.b == 2

Type casting

For configuration formats with type support, including dictionary, no type casting is done by this library, except that for TOML files.

TOML does not support None value in python. We use rtoml library to parse TOML files, which dumps None as "null". So a null_caster is used to cast "null" to None.

A none_caster is also enabled for TOML files, a pure string of "@none" is casted to None.

For other formats, following casters are supported:

Int caster

from os import environ
from simpleconf import Config

environ['XXX_A'] = '@int:1'

conf = Config.load('XXX.osenv')
# conf.a == 1 # int

Float caster

@float:1.0 -> 1.0

Bool caster

@bool:true -> True @bool:false -> False

Python caster

Values are casted by ast.literal_eval().

"@python:1" => 1  # or
"@py:1" => 1
"@py:1.0` -> `1.0`
"@py:[1, 2, 3]" => [1, 2, 3]

JSON caster

@json:{"a": 1} -> {"a": 1}

TOML caster

@toml:a = 1 -> {"a": 1}

Templated configuration files

jinja2 and liquid templating engines are supported. The templating engine is determined by the file extension, which can be either the primary or secondary suffix. For example, config.toml.j2 and config.j2.toml are both treated as TOML files with Jinja2 templating.

config.toml.j2

a = {{ 1 + 2 }}
from simpleconf import Config

conf = Config.load('config.toml.j2')
# conf.a == 3

config.liq.toml

{% for i in range(1, 3) %}
[section{{i}}]
a = {{i}}
{% endfor %}
from simpleconf import Config

conf = Config.load('config.liq.toml')
# conf.section1.a == 1
# conf.section2.a == 2

Loader directive in the first line

Instead of using a special file extension, you can embed a loader directive in the first line of a configuration file as a comment. This allows a plain config.toml to be processed by the Liquid engine without renaming the file.

The directive format is:

# simpleconf-loader: <loader>

Supported comment prefixes: #, ;, // (case-insensitive).

The <loader> value can be:

ValueMeaning
liq or liquidUse the Liquid loader for this file's format
j2, jinja, or jinja2Use the Jinja2 loader for this file's format
A full extension (e.g. toml.liq)Use the exact loader specified

Example — Liquid in a plain .toml file:

config.toml

# simpleconf-loader: liq
{% set x = 10 %}
[default]
a = {{ 1 + 1 }}
b = {{ x + 2 }}
from simpleconf import Config

conf = Config.load('config.toml')
# conf.default.a == 2
# conf.default.b == 12

Example — Jinja2 in a plain .yaml file:

config.yaml

# simpleconf-loader: j2
default:
  a: {{ 1 + 1 }}
from simpleconf import Config

conf = Config.load('config.yaml')
# conf.default.a == 2

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts