essentials-configuration


Nameessentials-configuration JSON
Version 2.0.4 PyPI version JSON
download
home_page
SummaryImplementation of key-value pair based configuration for Python applications.
upload_time2023-12-28 10:56:00
maintainer
docs_urlNone
author
requires_python>=3.7
license
keywords configuration management root settings strategy
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ![Build](https://github.com/Neoteroi/essentials-configuration/workflows/Build/badge.svg)
[![pypi](https://img.shields.io/pypi/v/essentials-configuration.svg)](https://pypi.python.org/pypi/essentials-configuration)
[![versions](https://img.shields.io/pypi/pyversions/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration)
[![codecov](https://codecov.io/gh/Neoteroi/essentials-configuration/branch/main/graph/badge.svg?token=VzAnusWIZt)](https://codecov.io/gh/Neoteroi/essentials-configuration)
[![license](https://img.shields.io/github/license/Neoteroi/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration/blob/main/LICENSE)

# Python configuration utilities
Implementation of key-value pair based configuration for Python applications.

**Features:**
- support for most common sources of application settings
- support for overriding settings in sequence
- support for nested structures and lists, using attribute notation
- strategy to use environment specific settings
- features to handle secrets and values stored in the user folder, for local
  development
- features to support validation of configuration items, for example using
  `pydantic`, or user defined classes

This library is freely inspired by .NET Core `Microsoft.Extensions.Configuration` (_ref. [MSDN documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1), [Microsoft Extensions Configuration Deep Dive](https://www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/)_).

The main class is influenced by Luciano Ramalho`s example of
JSON structure explorer using attribute notation, in his book [Fluent Python](http://shop.oreilly.com/product/0636920032519.do).

## Overview

`essentials-configuration` provides a way to handle configuration roots
composed of several layers, such as configuration files and environment
variables. Layers are applied in order and can override each others' values,
enabling different scenarios like configuration by environment and system
instance.

## Supported sources:
- **toml** files
- **yaml** files
- **json** files
- **ini** files
- environment variables
- secrets stored in the user folder, for development purpose
- dictionaries
- keys and values
- [Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts), using [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault)
- custom sources, implementing the `ConfigurationSource` interface

## Installation

```bash
pip install essentials-configuration
```

To install with support for `YAML` configuration files:

```
pip install essentials-configuration[yaml]
```

To install with support for `YAML` configuration files and the `CLI` to handle
user secrets:

```
pip install essentials-configuration[full]
```

## Extensions

* Azure Key Vault secrets configuration source:
  [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault)

# Examples

Please read the list of examples in the [examples folder](./examples). Below
are reported some of the examples that are tested in this repository.

### TOML file

```python
from config.common import ConfigurationBuilder
from config.env import EnvVars
from config.toml import TOMLFile


builder = ConfigurationBuilder(
    TOMLFile("settings.toml"),
    EnvVars(prefix="APP_")
)

config = builder.build()
```

For example, if the TOML file contains the following contents:

```toml
title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
```

And the environment has a variable such as `APP_OWNER__NAME=AAA`, the owner
name from the TOML file gets overridden by the env variable:

```python
>>> config
<Configuration {'title': '...', 'owner': '...'}>
>>> config.title
'TOML Example'
>>> config.owner.name
'AAA'
```

### JSON file and environment variables

In the following example, configuration values will include the structure
inside the file `settings.json` and environment variables whose name starts
with "APP_". Settings are applied in order, so environment variables with
matching name override values from the `json` file.

```python
from config.common import ConfigurationBuilder
from config.json import JSONFile
from config.env import EnvVars

builder = ConfigurationBuilder(
    JSONFile("settings.json"),
    EnvVars(prefix="APP_")
)

config = builder.build()
```

For example, if the JSON file contains the following contents:

```json
{
    "logging": {
        "level": "INFO"
    },
    "example": "Hello World",
    "foo": "foo"
}
```

And the environment has a variable named `APP_foo=AAA`:

```python
>>> config
<Configuration {'logging': '...', 'example': '...', 'foo': '...'}>
>>> config.foo
'AAA'
>>> config.logging.level
'INFO'
```

### YAML file and environment variables

In this example, configuration will include anything inside a file
`settings.yaml` and environment variables. Settings are applied in order, so
environment variables with matching name override values from the `yaml` file
(using the `yaml` source requires also `PyYAML` package).


```python
from config.common import ConfigurationBuilder
from config.env import EnvVars
from config.yaml import YAMLFile

builder = ConfigurationBuilder()

builder.add_source(YAMLFile("settings.yaml"))
builder.add_source(EnvVars())

config = builder.build()
```

### YAML file, optional file by environment

In this example, if an environment variable with name `APP_ENVIRONMENT` and
value `dev` exists, and a configuration file with name `settings.dev.yaml` is
present, it is read to override values configured in `settings.yaml` file.

```python
import os

from config.common import ConfigurationBuilder
from config.env import EnvVars
from config.yaml import YAMLFile

environment_name = os.environ["APP_ENVIRONMENT"]

builder = ConfigurationBuilder(
    YAMLFile("settings.yaml"),
    YAMLFile(f"settings.{environment_name}.yaml", optional=True)
)

config = builder.build()
```

### Filtering environment variables by prefix

```python
from config.common import ConfigurationBuilder
from config.env import EnvVars

builder = ConfigurationBuilder()

builder.add_source(EnvVars(prefix="APP_"))

config = builder.build()
```

### INI files

INI files are parsed using the built-in `configparser` module, therefore
support `[DEFAULT]` section; all values are kept as strings.

```python
from config.common import ConfigurationBuilder
from config.ini import INIFile

builder = ConfigurationBuilder()

builder.add_source(INIFile("settings.ini"))

config = builder.build()
```

### Dictionaries

```python
from config.common import ConfigurationBuilder

builder = ConfigurationBuilder()

builder.add_map({"host": "localhost", "port": 8080})

builder.add_map({"hello": "world", "example": [{"id": 1}, {"id": 2}]})

config = builder.build()

assert config.host == "localhost"
assert config.port == 8080
assert config.hello == "world"
assert config.example[0].id == 1
assert config.example[1].id == 2
```

### Keys and values

```python
from config.common import ConfigurationBuilder

builder = ConfigurationBuilder()

builder.add_map({"host": "localhost", "port": 8080})

builder.add_value("port", 44555)

config = builder.build()

assert config.host == "localhost"
assert config.port == 44555
```

### User secrets

The library provides a strategy to handle secrets during local development,
storing them into the user folder.

The following example shows how secrets can be configured for a project:

```bash
config settings init
config settings set "Foo" "Some secret value"
```

Secrets are organized by project, and the project information is obtained from
`pyproject.toml` files (from the `project.name` property). If `pyproject.toml`
file does not exist, one is generated automatically with a random name.

---

Then, from a Python app, it's possible to load the secrets from the user folder:

```python
from config.common import ConfigurationBuilder
from config.json import JSONFile
from config.secrets import UserSecrets

builder = ConfigurationBuilder(JSONFile("settings.json"), UserSecrets())

config = builder.build()

print(config)
# config contains both values from `settings.json`, and secrets read from the user
# folder
```

Secrets are optional and should be used only for local development, they are
stored in unencrypted form in the user's folder.

Production apps should use dedicated services to handle secrets, like
[Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts),
[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or similar services.
For Azure Key Vault, an implementation is provided in [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault).

## Handling user settings

User settings (stored in the user's folder) can be handled using the provided `config` CLI.

![Rich CLI](https://gist.githubusercontent.com/RobertoPrevato/38a0598b515a2f7257c614938843b99b/raw/a83facd6eb4ddc1dc8552a5f5f073278470010c2/config-settings-rich-cli.png)

These settings can be useful to store secrets and other values during local development, or in general when working with desktop applications.

### Overriding nested values

It is possible to override nested values by environment variables or
dictionary keys using the following notation for sub properties:

* keys separated by colon ":", such as `a:d:e`
* keys separated by "__", such as `a__d__e`

```python
from config.common import ConfigurationBuilder, MapSource


builder = ConfigurationBuilder(
    MapSource(
        {
            "a": {
                "b": 1,
                "c": 2,
                "d": {
                    "e": 3,
                    "f": 4,
                },
            }
        }
    )
)

config = builder.build()

assert config.a.b == 1
assert config.a.d.e == 3
assert config.a.d.f == 4

builder.add_value("a:d:e", 5)

config = builder.build()

assert config.a.d.e == 5
assert config.a.d.f == 4

```

### Overriding nested values using env variables

```python
import os

from config.common import ConfigurationBuilder, MapSource
from config.env import EnvVars

builder = ConfigurationBuilder(
    MapSource(
        {
            "a": {
                "b": 1,
                "c": 2,
                "d": {
                    "e": 3,
                    "f": 4,
                },
            }
        }
    )
)

config = builder.build()

assert config.a.b == 1
assert config.a.d.e == 3
assert config.a.d.f == 4

# NB: if an env variable such as:
# a:d:e=5
# or...
# a__d__e=5
#
# is defined, it overrides the value  from the dictionary

os.environ["a__d__e"] = "5"

builder.sources.append(EnvVars())

config = builder.build()

assert config.a.d.e == "5"
```

### Overriding values in list items using env variables

```python
import os

from config.common import ConfigurationBuilder, MapSource
from config.env import EnvVars

builder = ConfigurationBuilder(
    MapSource(
        {
            "b2c": [
                {"tenant": "1"},
                {"tenant": "2"},
                {"tenant": "3"},
            ]
        }
    ),
    EnvVars(),
)

os.environ["b2c__0__tenant"] = "5"

config = builder.build()

assert config.b2c[0].tenant == "5"
assert config.b2c[1].tenant == "2"
assert config.b2c[2].tenant == "3"
```

### Typed config

To bind configuration sections with types checking, for example to use `pydantic` to
validate application settings, use the `config.bind` method like in
the following example:

```yaml
# example-01.yaml
foo:
  value: "foo"
  x: 100
```

```python
# example
from pydantic import BaseModel

from config.common import ConfigurationBuilder
from config.yaml import YAMLFile


class FooSettings(BaseModel):
    value: str
    x: int


builder = ConfigurationBuilder(YAMLFile("example-01.yaml"))

config = builder.build()

# the bind method accepts a variable number of fragments to
# obtain the configuration section that should be used to instantiate the given type
foo_settings = config.bind(FooSettings, "foo")

assert isinstance(foo_settings, FooSettings)
assert foo_settings.value == "foo"
assert foo_settings.x == 100
```

### Goal and non-goals

The goal of this package is to provide a way to handle configuration roots,
fetching and composing settings from different sources, usually happening
once at application's start.

The library implements only a synchronous API and fetching of application
settings atomically (it doesn't support generators), like application settings
fetched from INI, JSON, or YAML files that are read once in memory entirely.
An asynchronous API is currently out of the scope of this library, since its
primary use case is to fetch configuration values once at application's start.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "essentials-configuration",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "configuration,management,root,settings,strategy",
    "author": "",
    "author_email": "Roberto Prevato <roberto.prevato@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/c3/eb/97851b25684057e8f4451cb86c1d912ddf2fbafa300e2fdb20e6fe1ca6a6/essentials_configuration-2.0.4.tar.gz",
    "platform": null,
    "description": "![Build](https://github.com/Neoteroi/essentials-configuration/workflows/Build/badge.svg)\n[![pypi](https://img.shields.io/pypi/v/essentials-configuration.svg)](https://pypi.python.org/pypi/essentials-configuration)\n[![versions](https://img.shields.io/pypi/pyversions/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration)\n[![codecov](https://codecov.io/gh/Neoteroi/essentials-configuration/branch/main/graph/badge.svg?token=VzAnusWIZt)](https://codecov.io/gh/Neoteroi/essentials-configuration)\n[![license](https://img.shields.io/github/license/Neoteroi/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration/blob/main/LICENSE)\n\n# Python configuration utilities\nImplementation of key-value pair based configuration for Python applications.\n\n**Features:**\n- support for most common sources of application settings\n- support for overriding settings in sequence\n- support for nested structures and lists, using attribute notation\n- strategy to use environment specific settings\n- features to handle secrets and values stored in the user folder, for local\n  development\n- features to support validation of configuration items, for example using\n  `pydantic`, or user defined classes\n\nThis library is freely inspired by .NET Core `Microsoft.Extensions.Configuration` (_ref. [MSDN documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1), [Microsoft Extensions Configuration Deep Dive](https://www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/)_).\n\nThe main class is influenced by Luciano Ramalho`s example of\nJSON structure explorer using attribute notation, in his book [Fluent Python](http://shop.oreilly.com/product/0636920032519.do).\n\n## Overview\n\n`essentials-configuration` provides a way to handle configuration roots\ncomposed of several layers, such as configuration files and environment\nvariables. Layers are applied in order and can override each others' values,\nenabling different scenarios like configuration by environment and system\ninstance.\n\n## Supported sources:\n- **toml** files\n- **yaml** files\n- **json** files\n- **ini** files\n- environment variables\n- secrets stored in the user folder, for development purpose\n- dictionaries\n- keys and values\n- [Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts), using [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault)\n- custom sources, implementing the `ConfigurationSource` interface\n\n## Installation\n\n```bash\npip install essentials-configuration\n```\n\nTo install with support for `YAML` configuration files:\n\n```\npip install essentials-configuration[yaml]\n```\n\nTo install with support for `YAML` configuration files and the `CLI` to handle\nuser secrets:\n\n```\npip install essentials-configuration[full]\n```\n\n## Extensions\n\n* Azure Key Vault secrets configuration source:\n  [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault)\n\n# Examples\n\nPlease read the list of examples in the [examples folder](./examples). Below\nare reported some of the examples that are tested in this repository.\n\n### TOML file\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.env import EnvVars\nfrom config.toml import TOMLFile\n\n\nbuilder = ConfigurationBuilder(\n    TOMLFile(\"settings.toml\"),\n    EnvVars(prefix=\"APP_\")\n)\n\nconfig = builder.build()\n```\n\nFor example, if the TOML file contains the following contents:\n\n```toml\ntitle = \"TOML Example\"\n\n[owner]\nname = \"Tom Preston-Werner\"\n```\n\nAnd the environment has a variable such as `APP_OWNER__NAME=AAA`, the owner\nname from the TOML file gets overridden by the env variable:\n\n```python\n>>> config\n<Configuration {'title': '...', 'owner': '...'}>\n>>> config.title\n'TOML Example'\n>>> config.owner.name\n'AAA'\n```\n\n### JSON file and environment variables\n\nIn the following example, configuration values will include the structure\ninside the file `settings.json` and environment variables whose name starts\nwith \"APP_\". Settings are applied in order, so environment variables with\nmatching name override values from the `json` file.\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.json import JSONFile\nfrom config.env import EnvVars\n\nbuilder = ConfigurationBuilder(\n    JSONFile(\"settings.json\"),\n    EnvVars(prefix=\"APP_\")\n)\n\nconfig = builder.build()\n```\n\nFor example, if the JSON file contains the following contents:\n\n```json\n{\n    \"logging\": {\n        \"level\": \"INFO\"\n    },\n    \"example\": \"Hello World\",\n    \"foo\": \"foo\"\n}\n```\n\nAnd the environment has a variable named `APP_foo=AAA`:\n\n```python\n>>> config\n<Configuration {'logging': '...', 'example': '...', 'foo': '...'}>\n>>> config.foo\n'AAA'\n>>> config.logging.level\n'INFO'\n```\n\n### YAML file and environment variables\n\nIn this example, configuration will include anything inside a file\n`settings.yaml` and environment variables. Settings are applied in order, so\nenvironment variables with matching name override values from the `yaml` file\n(using the `yaml` source requires also `PyYAML` package).\n\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.env import EnvVars\nfrom config.yaml import YAMLFile\n\nbuilder = ConfigurationBuilder()\n\nbuilder.add_source(YAMLFile(\"settings.yaml\"))\nbuilder.add_source(EnvVars())\n\nconfig = builder.build()\n```\n\n### YAML file, optional file by environment\n\nIn this example, if an environment variable with name `APP_ENVIRONMENT` and\nvalue `dev` exists, and a configuration file with name `settings.dev.yaml` is\npresent, it is read to override values configured in `settings.yaml` file.\n\n```python\nimport os\n\nfrom config.common import ConfigurationBuilder\nfrom config.env import EnvVars\nfrom config.yaml import YAMLFile\n\nenvironment_name = os.environ[\"APP_ENVIRONMENT\"]\n\nbuilder = ConfigurationBuilder(\n    YAMLFile(\"settings.yaml\"),\n    YAMLFile(f\"settings.{environment_name}.yaml\", optional=True)\n)\n\nconfig = builder.build()\n```\n\n### Filtering environment variables by prefix\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.env import EnvVars\n\nbuilder = ConfigurationBuilder()\n\nbuilder.add_source(EnvVars(prefix=\"APP_\"))\n\nconfig = builder.build()\n```\n\n### INI files\n\nINI files are parsed using the built-in `configparser` module, therefore\nsupport `[DEFAULT]` section; all values are kept as strings.\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.ini import INIFile\n\nbuilder = ConfigurationBuilder()\n\nbuilder.add_source(INIFile(\"settings.ini\"))\n\nconfig = builder.build()\n```\n\n### Dictionaries\n\n```python\nfrom config.common import ConfigurationBuilder\n\nbuilder = ConfigurationBuilder()\n\nbuilder.add_map({\"host\": \"localhost\", \"port\": 8080})\n\nbuilder.add_map({\"hello\": \"world\", \"example\": [{\"id\": 1}, {\"id\": 2}]})\n\nconfig = builder.build()\n\nassert config.host == \"localhost\"\nassert config.port == 8080\nassert config.hello == \"world\"\nassert config.example[0].id == 1\nassert config.example[1].id == 2\n```\n\n### Keys and values\n\n```python\nfrom config.common import ConfigurationBuilder\n\nbuilder = ConfigurationBuilder()\n\nbuilder.add_map({\"host\": \"localhost\", \"port\": 8080})\n\nbuilder.add_value(\"port\", 44555)\n\nconfig = builder.build()\n\nassert config.host == \"localhost\"\nassert config.port == 44555\n```\n\n### User secrets\n\nThe library provides a strategy to handle secrets during local development,\nstoring them into the user folder.\n\nThe following example shows how secrets can be configured for a project:\n\n```bash\nconfig settings init\nconfig settings set \"Foo\" \"Some secret value\"\n```\n\nSecrets are organized by project, and the project information is obtained from\n`pyproject.toml` files (from the `project.name` property). If `pyproject.toml`\nfile does not exist, one is generated automatically with a random name.\n\n---\n\nThen, from a Python app, it's possible to load the secrets from the user folder:\n\n```python\nfrom config.common import ConfigurationBuilder\nfrom config.json import JSONFile\nfrom config.secrets import UserSecrets\n\nbuilder = ConfigurationBuilder(JSONFile(\"settings.json\"), UserSecrets())\n\nconfig = builder.build()\n\nprint(config)\n# config contains both values from `settings.json`, and secrets read from the user\n# folder\n```\n\nSecrets are optional and should be used only for local development, they are\nstored in unencrypted form in the user's folder.\n\nProduction apps should use dedicated services to handle secrets, like\n[Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts),\n[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or similar services.\nFor Azure Key Vault, an implementation is provided in [essentials-configuration-keyvault](https://github.com/Neoteroi/essentials-configuration-keyvault).\n\n## Handling user settings\n\nUser settings (stored in the user's folder) can be handled using the provided `config` CLI.\n\n![Rich CLI](https://gist.githubusercontent.com/RobertoPrevato/38a0598b515a2f7257c614938843b99b/raw/a83facd6eb4ddc1dc8552a5f5f073278470010c2/config-settings-rich-cli.png)\n\nThese settings can be useful to store secrets and other values during local development, or in general when working with desktop applications.\n\n### Overriding nested values\n\nIt is possible to override nested values by environment variables or\ndictionary keys using the following notation for sub properties:\n\n* keys separated by colon \":\", such as `a:d:e`\n* keys separated by \"__\", such as `a__d__e`\n\n```python\nfrom config.common import ConfigurationBuilder, MapSource\n\n\nbuilder = ConfigurationBuilder(\n    MapSource(\n        {\n            \"a\": {\n                \"b\": 1,\n                \"c\": 2,\n                \"d\": {\n                    \"e\": 3,\n                    \"f\": 4,\n                },\n            }\n        }\n    )\n)\n\nconfig = builder.build()\n\nassert config.a.b == 1\nassert config.a.d.e == 3\nassert config.a.d.f == 4\n\nbuilder.add_value(\"a:d:e\", 5)\n\nconfig = builder.build()\n\nassert config.a.d.e == 5\nassert config.a.d.f == 4\n\n```\n\n### Overriding nested values using env variables\n\n```python\nimport os\n\nfrom config.common import ConfigurationBuilder, MapSource\nfrom config.env import EnvVars\n\nbuilder = ConfigurationBuilder(\n    MapSource(\n        {\n            \"a\": {\n                \"b\": 1,\n                \"c\": 2,\n                \"d\": {\n                    \"e\": 3,\n                    \"f\": 4,\n                },\n            }\n        }\n    )\n)\n\nconfig = builder.build()\n\nassert config.a.b == 1\nassert config.a.d.e == 3\nassert config.a.d.f == 4\n\n# NB: if an env variable such as:\n# a:d:e=5\n# or...\n# a__d__e=5\n#\n# is defined, it overrides the value  from the dictionary\n\nos.environ[\"a__d__e\"] = \"5\"\n\nbuilder.sources.append(EnvVars())\n\nconfig = builder.build()\n\nassert config.a.d.e == \"5\"\n```\n\n### Overriding values in list items using env variables\n\n```python\nimport os\n\nfrom config.common import ConfigurationBuilder, MapSource\nfrom config.env import EnvVars\n\nbuilder = ConfigurationBuilder(\n    MapSource(\n        {\n            \"b2c\": [\n                {\"tenant\": \"1\"},\n                {\"tenant\": \"2\"},\n                {\"tenant\": \"3\"},\n            ]\n        }\n    ),\n    EnvVars(),\n)\n\nos.environ[\"b2c__0__tenant\"] = \"5\"\n\nconfig = builder.build()\n\nassert config.b2c[0].tenant == \"5\"\nassert config.b2c[1].tenant == \"2\"\nassert config.b2c[2].tenant == \"3\"\n```\n\n### Typed config\n\nTo bind configuration sections with types checking, for example to use `pydantic` to\nvalidate application settings, use the `config.bind` method like in\nthe following example:\n\n```yaml\n# example-01.yaml\nfoo:\n  value: \"foo\"\n  x: 100\n```\n\n```python\n# example\nfrom pydantic import BaseModel\n\nfrom config.common import ConfigurationBuilder\nfrom config.yaml import YAMLFile\n\n\nclass FooSettings(BaseModel):\n    value: str\n    x: int\n\n\nbuilder = ConfigurationBuilder(YAMLFile(\"example-01.yaml\"))\n\nconfig = builder.build()\n\n# the bind method accepts a variable number of fragments to\n# obtain the configuration section that should be used to instantiate the given type\nfoo_settings = config.bind(FooSettings, \"foo\")\n\nassert isinstance(foo_settings, FooSettings)\nassert foo_settings.value == \"foo\"\nassert foo_settings.x == 100\n```\n\n### Goal and non-goals\n\nThe goal of this package is to provide a way to handle configuration roots,\nfetching and composing settings from different sources, usually happening\nonce at application's start.\n\nThe library implements only a synchronous API and fetching of application\nsettings atomically (it doesn't support generators), like application settings\nfetched from INI, JSON, or YAML files that are read once in memory entirely.\nAn asynchronous API is currently out of the scope of this library, since its\nprimary use case is to fetch configuration values once at application's start.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Implementation of key-value pair based configuration for Python applications.",
    "version": "2.0.4",
    "project_urls": {
        "Bug Tracker": "https://github.com/Neoteroi/essentials-configuration/issues",
        "Homepage": "https://github.com/Neoteroi/essentials-configuration"
    },
    "split_keywords": [
        "configuration",
        "management",
        "root",
        "settings",
        "strategy"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "76c1d72254fd026846e56b5d90a51682449cd6f7df95f093810194a4de47dae0",
                "md5": "4175b7af356624b6c0c45dc958e20289",
                "sha256": "d3c81376a82c52aa68367c082c4d9015cc77a0dc322b2588898ced67d7ae5382"
            },
            "downloads": -1,
            "filename": "essentials_configuration-2.0.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4175b7af356624b6c0c45dc958e20289",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 16078,
            "upload_time": "2023-12-28T10:55:59",
            "upload_time_iso_8601": "2023-12-28T10:55:59.227288Z",
            "url": "https://files.pythonhosted.org/packages/76/c1/d72254fd026846e56b5d90a51682449cd6f7df95f093810194a4de47dae0/essentials_configuration-2.0.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c3eb97851b25684057e8f4451cb86c1d912ddf2fbafa300e2fdb20e6fe1ca6a6",
                "md5": "53b4cb43d1a89e912f6df1e21aac1e35",
                "sha256": "b23f7a0f23f2ad6011339e4866e500e5efda2480f27f1f41e378bb04238412d8"
            },
            "downloads": -1,
            "filename": "essentials_configuration-2.0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "53b4cb43d1a89e912f6df1e21aac1e35",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 11328,
            "upload_time": "2023-12-28T10:56:00",
            "upload_time_iso_8601": "2023-12-28T10:56:00.975940Z",
            "url": "https://files.pythonhosted.org/packages/c3/eb/97851b25684057e8f4451cb86c1d912ddf2fbafa300e2fdb20e6fe1ca6a6/essentials_configuration-2.0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-28 10:56:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Neoteroi",
    "github_project": "essentials-configuration",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "essentials-configuration"
}
        
Elapsed time: 0.15825s