Name | configzen JSON |
Version |
0.10.0
JSON |
| download |
home_page | https://github.com/bswck/configzen |
Summary | The easiest way to manage configuration files in Python |
upload_time | 2023-08-23 21:12:51 |
maintainer | |
docs_url | None |
author | bswck |
requires_python | >=3.8,<4.0 |
license | MIT |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# configzen `v0.10.0`
_configzen_ – easily create and maintain complex, statically-typed configurations with validation in Python.
It's important to keep your configuration safe and consistent. Give a shot to _configzen_ 🚀
⭐ Supports **Python 3.8 or above**,<br>
⭐ Is **fully typed**,<br>
⭐ Supports **YAML, JSON, TOML, INI, XML, ConfigObj, BSON, CBOR, Amazon Ion, properties** and **shellvars**,<br>
⭐ Supports **reading and writing configuration files**, fully or partially, with the ability to preserve the original file structure (without comments[^1]),<br>
⭐ Supports **configuration preprocessing** (extending, including and copying configuration files without the need to change the code),<br>
⭐ Supports **variable interpolation** (runtime value substitution),<br>
⭐ Supports **modular configuration with type validation** (wrapping runtime Python modules in-place and outside them),<br>
⭐ Supports **synchronous and asynchronous file operations**,<br>
⭐ Supports loading configuration from **environment variables and secret files**.<br>
While being built on top of [pydantic](https://docs.pydantic.dev/1.10/), _configzen_ inherits most of its features, including
[data validation](https://docs.pydantic.dev/1.10/usage/validators/), [schema generation](https://docs.pydantic.dev/1.10/usage/schema/),
[custom data types](https://docs.pydantic.dev/1.10/usage/types/#arbitrary-types-allowed), good integration with [Rich](https://docs.pydantic.dev/1.10/usage/rich/), and more.
Learn more below.
## Features
### Managing content
Having a YAML configuration file like this:
```yaml
# database.yml
host: 127.0.0.1
port: 5432
user: postgres
```
You can create a _configzen_ configuration model for it like this:
```python
# model.py
from ipaddress import IPv4Address, IPv6Address
from configzen import ConfigField, ConfigMeta, ConfigModel
class DatabaseConfig(ConfigModel):
host: IPv4Address | IPv6Address
port: int
user: str
password: str = ConfigField(exclude=True)
class Config(ConfigMeta):
resource = "database.yml"
env_prefix = "DB_"
db_config = DatabaseConfig.load()
```
And you can load your configuration from a file as well as from the environment variables
`DB_HOST`, `DB_PORT`, `DB_USER` and `DB_PASSWORD`. Since `password` is a field created with
the option `exclude=True`, it will not be included in the configuration's exported data: that
guarantees that your password does never leak into `database.yml` on save – but you may still pass it
through an environment variable (here – the mentioned `DB_PASSWORD`). Secret files are also supported,
see [the pydantic documentation](https://docs.pydantic.dev/latest/usage/settings/#secret-support)
for more information.
[pydantic](https://docs.pydantic.dev/latest/) will naturally take care of parsing and validating the loaded data.
Configuration models inherit from the `pydantic.BaseSettings` class, so you can use all of its features:
schema generation, type conversion, validation, etc.
There are additional features brought to you by _configzen_ worth checking out, though.
You can use the `db_config` object defined above to access the configuration values:
```python
>>> db_config.host
IPv4Address('127.0.0.1')
```
modify them, if the pydantic model validation allows
it ([`<Your model>.Config.validate_assignment`](https://docs.pydantic.dev/latest/usage/model_config/#options) will
be `True` by default):
```python
>>> db_config.host = "0.0.0.0"
>>> db_config.host
IPv4Address('0.0.0.0')
```
as well as reload particular values, without touching the rest of the configuration:
```python
>>> db_config.at("port").reload()
5432
>>> db_config
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')
>>> db_config.at("host").reload()
IPv4Address('127.0.0.1')
>>> db_config
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')
```
or reload the whole configuration:
```python
>>> db_config.port = 1234
>>> db_config.reload()
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')
```
or save a particular value, without touching the rest of the configuration:
```python
>>> db_config.host = "0.0.0.0"
>>> db_config.port = 443
>>> db_config
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=443, user='postgres', password='password')
>>> db_config.at("host").save()
40
>>> db_config.reload()
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')
```
or save the whole configuration:
```python
>>> db_config.save()
39
```
### Preprocessing
To see supported preprocessing directives,
see [Supported preprocessing directives](#supported-preprocessing-directives).
#### Basic usage
Having a base configuration file like this (`base.json`):
```json
{
"i18n": {
"language": "en",
"timezone": "UTC"
},
"app": {
"debug": true,
"expose": 8000
}
}
```
create another configuration file like this, overriding desired sections as needed:
```yaml
# production.yml
^extend: base.json
+app:
debug: false
```
and load the `production.yml` configuration file. No explicit changes to the code indicating the use of the `base.json`
file are needed.
_Note: Using `+` in front of a key will update the section already defined at that key,
instead of overwriting it entirely._
Notice how configuration file formats do not matter in _configzen_: you can
extend JSON configurations with YAML, but that might be as well any other format
among the supported ones (see the [Supported file formats](#supported-file-formats) section).
The above example is equivalent to as if you used:
```yaml
# production.yml
i18n:
language: en
timezone: UTC
app:
debug: false
expose: 8000
```
but with a significant difference: when you save the above configuration, the `^extend` relation to the base
configuration file `base.json` is preserved.
This basically means that changes made in the base configuration file will apply to the configuration model instance
loaded from the `^extend`-ing configuration file.
Any changes made locally to the model will result in `+` sections being automatically added to the exported
configuration data.
#### Supported preprocessing directives
| Directive | Is the referenced file preprocessed? | Is the directive preserved on export? |
| ---------- | ------------------------------------ | ------------------------------------- |
| `^extend` | Yes | Yes |
| `^include` | Yes | No |
| `^copy` | No | No |
### Interpolation
#### Basic interpolation
You can use interpolation in your configuration files:
```yaml
cpu:
cores: 4
num_workers: ${cpu.cores}
```
```python
>>> from configzen import ConfigModel
...
>>> class CPUConfig(ConfigModel):
... cores: int
...
>>> class AppConfig(ConfigModel):
... cpu: CPUConfig
... num_workers: int
...
>>> app_config = AppConfig.load("app.yml")
>>> app_config
AppConfig(cpu=CPUConfig(cores=4), num_workers=4)
```
#### Reusable configuration with namespaces
You can share independent configuration models as namespaces through inclusion:
```yaml
# database.yml
host: ${app_config::db_host}
port: ${app_config::expose}
```
```yaml
# app.yml
db_host: localhost
expose: 8000
```
```python
>>> from configzen import ConfigModel, include
>>> from ipaddress import IPv4Address
>>>
>>> @include("app_config")
... class DatabaseConfig(ConfigModel):
... host: IPv4Address
... port: int
...
>>> class AppConfig(ConfigModel):
... db_host: str
... expose: int
...
>>> app_config = AppConfig.load("app.yml")
>>> app_config
AppConfig(db_host='localhost', expose=8000)
>>> db_config = DatabaseConfig.load("database.yml")
>>> db_config
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=8000)
>>> db_config.dict()
{'host': IPv4Address('127.0.0.1'), 'port': 8000}
>>> db_config.export() # used when saving
{'host': '${app_config::db_host}', 'port': '${app_config::expose}'}
```
You do not have to pass a variable name to `@include`, though. `@include` lets you overwrite the main interpolation namespace
or one with a separate name (here: `app_config`) with configuration models, dictionaries and their factories.
### Modular configuration
#### Wrapping modules in-place
You can wrap modules in-place with configuration models:
1) Without writing a model class:
```python
# config.py
from configzen import ConfigModule
# Annotate config fields
HOST: str = "localhost"
PORT: int = 8000
ConfigModule.wrap_this_module()
```
2) With a model class:
```python
# config.py
from configzen import ConfigModel
# Annotations are optional
HOST = "localhost"
PORT = 8000
class AppConfig(ConfigModel):
HOST: str
PORT: int
AppConfig.wrap_this_module()
```
Now values `HOST` and `PORT` will be validated as `str` and `int` data types, respectively:
```python
>>> import config # <configuration module 'config' from 'config.py'>
>>> config.HOST
'localhost'
>>> config.PORT
8000
>>> config.PORT = "8000"
>>> config.PORT
8000
>>> config.PORT = "abc"
Traceback (most recent call last):
...
```
#### Wrapping interchangeable modules
You can wrap modules outside them with configuration models:
```python
# setup.py
from configzen import ConfigModel
class AppConfig(ConfigModel):
HOST: str = "localhost"
PORT: int = 8000
config_model = AppConfig.wrap_module("config")
```
```py
# config.py
HOST: str = "0.0.0.0"
PORT: int = 443
```
```python
>>> from setup import config_model
>>> config_model.HOST
'0.0.0.0'
>>> config_model.PORT
443
>>> config_model.PORT = "8000"
>>> config_model.PORT
8000
>>> import config
>>> config.HOST
'0.0.0.0'
>>> config.PORT
8000
```
## Supported file formats
_configzen_ uses [anyconfig](https://pypi.org/project/anyconfig/) to serialize and deserialize data and does not operate on any protocol-specific entities.
As an example result, comments in your configuration files are lost on save[^1], but you can exchange file formats without any hassle.
The following table shows the supported file formats, their requirements, file extensions, and the backend libraries used to accomplish this goal.
| File Format | To use, install: | Recognized File Extension(s) | Backend Library |
| ----------------------------------------------------------------------------------- | ----------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------- |
| [JSON](https://en.wikipedia.org/wiki/JSON) | - | `json` | [json](https://docs.python.org/3/library/json.html) (standard library) |
| [INI](https://en.wikipedia.org/wiki/INI_file) | - | `ini`, `cfg`, `conf` | [configparser](https://docs.python.org/3/library/configparser.html) (standard library) |
| [TOML](https://en.wikipedia.org/wiki/TOML) | - | `toml` | [toml](https://pypi.python.org/pypi/toml) |
| [YAML](https://yaml.org) | - | `yaml`, `yml` | [pyyaml](https://pypi.python.org/pypi/PyYAML) / [ruamel.yaml](https://pypi.python.org/pypi/ruamel.yaml) |
| [XML](https://en.wikipedia.org/wiki/XML) | - | `xml` | [xml](https://docs.python.org/3/library/xml.html) (standard library) |
| [ConfigObj](https://configobj.readthedocs.io/en/latest/configobj.html#introduction) | `anyconfig-configobj-backend` | `configobj` | [configobj](https://pypi.org/project/configobj/) |
| [BSON](https://en.wikipedia.org/wiki/BSON) | `anyconfig-bson-backend` | `bson` | [bson](https://pypi.org/project/bson/) |
| [CBOR](https://cbor.io/) ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)) | `anyconfig-cbor2-backend` | `cbor`, `cbor2` | [cbor2](https://pypi.org/project/cbor2/) |
| [Amazon Ion](https://en.wikipedia.org/wiki/Ion_(serialization_format)) | `anyconfig-ion-backend` | `ion` | [ion](https://pypi.org/project/amazon.ion/) |
| CBOR (deprecated, [RFC 7049](https://www.rfc-editor.org/rfc/rfc7049)) | `anyconfig-cbor-backend` | `cbor` | [cbor](https://pypi.org/project/cbor/) |
| properties | - | `properties` | (native) |
| shellvars | - | `shellvars` | (native) |
<!-- Add msgpack when it works -->
If your file extension is not recognized, you can register your own file extension by calling `ConfigAgent.register_file_extension(file_extension, parser_name)`.
If your favorite backend library is not supported, please let me know by reporting it as an issue.
Using custom backends is to be supported in the future.
[^1]: A suggested alternative for comments is to use the `description` parameter in your configuration models' fields: `ConfigField(description=...)`.
The provided field descriptions are included in JSON schemas generated by the default implementation of the `ConfigModel.schema()` method.
## Setup
In order to use _configzen_ in your project, install it with your package manager, for example `pip`:
```bash
pip install configzen
```
If you are willing to contribute to _configzen_, which is awesome, simply clone this repository and install its
dependencies with [poetry](https://python-poetry.org/):
```bash
poetry install --with dev --all-extras
```
After that, install the [pre-commit](https://pre-commit.com/) hooks:
```bash
pre-commit install --hook-type pre-commit --hook-type pre-push
```
You might also need to install required stubs. First, activate your virtual environment:
```bash
poetry shell
```
and run (on Linux or [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.3) 7.0+):
```bash
mypy configzen/ || (echo yes | mypy --install-types)
```
or, if you are using an older version of PowerShell:
```powershell
mypy configzen/; if (-not $?) { echo yes | mypy --install-types }
```
_Note: Using [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) + [pyenv](https://github.com/pyenv/pyenv#readme) (with Python 3.8) for developing configzen is strongly recommended in case you use Windows._
And you are good to go. 🚀
Contributions are welcome! Feel free to [open an issue](https://github.com/bswck/configzen/issues/new/choose) whenever
you encounter a bug or have a feature request or [submit a pull request](https://github.com/bswck/configzen/compare) with your changes.
## License
[MIT License](https://choosealicense.com/licenses/mit/)
## Credits
* [@Lunarmagpie](https://github.com/Lunarmagpie) for _crucial_ design tips and ideas.
## Author
* [bswck](https://github.com/bswck) (contact: bswck.dev@gmail.com or via [Discord](https://discord.com/) `bswck`)
Raw data
{
"_id": null,
"home_page": "https://github.com/bswck/configzen",
"name": "configzen",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "bswck",
"author_email": "bswck.dev@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/71/85/08835a39768c2c60cdef84659b213394f6f7e91bd05ba4c9cf626365a001/configzen-0.10.0.tar.gz",
"platform": null,
"description": "# configzen `v0.10.0`\n\n_configzen_ \u2013 easily create and maintain complex, statically-typed configurations with validation in Python.\n\nIt's important to keep your configuration safe and consistent. Give a shot to _configzen_ \ud83d\ude80\n\n\u2b50 Supports **Python 3.8 or above**,<br>\n\u2b50 Is **fully typed**,<br>\n\u2b50 Supports **YAML, JSON, TOML, INI, XML, ConfigObj, BSON, CBOR, Amazon Ion, properties** and **shellvars**,<br>\n\u2b50 Supports **reading and writing configuration files**, fully or partially, with the ability to preserve the original file structure (without comments[^1]),<br>\n\u2b50 Supports **configuration preprocessing** (extending, including and copying configuration files without the need to change the code),<br>\n\u2b50 Supports **variable interpolation** (runtime value substitution),<br>\n\u2b50 Supports **modular configuration with type validation** (wrapping runtime Python modules in-place and outside them),<br>\n\u2b50 Supports **synchronous and asynchronous file operations**,<br>\n\u2b50 Supports loading configuration from **environment variables and secret files**.<br>\n\nWhile being built on top of [pydantic](https://docs.pydantic.dev/1.10/), _configzen_ inherits most of its features, including\n[data validation](https://docs.pydantic.dev/1.10/usage/validators/), [schema generation](https://docs.pydantic.dev/1.10/usage/schema/),\n[custom data types](https://docs.pydantic.dev/1.10/usage/types/#arbitrary-types-allowed), good integration with [Rich](https://docs.pydantic.dev/1.10/usage/rich/), and more.\n\nLearn more below.\n\n## Features\n\n### Managing content\n\nHaving a YAML configuration file like this:\n\n```yaml\n# database.yml\nhost: 127.0.0.1\nport: 5432\nuser: postgres\n```\n\nYou can create a _configzen_ configuration model for it like this:\n\n```python\n# model.py\nfrom ipaddress import IPv4Address, IPv6Address\n\nfrom configzen import ConfigField, ConfigMeta, ConfigModel\n\n\nclass DatabaseConfig(ConfigModel):\n host: IPv4Address | IPv6Address\n port: int\n user: str\n password: str = ConfigField(exclude=True)\n\n class Config(ConfigMeta):\n resource = \"database.yml\"\n env_prefix = \"DB_\"\n\n\ndb_config = DatabaseConfig.load()\n```\n\nAnd you can load your configuration from a file as well as from the environment variables\n`DB_HOST`, `DB_PORT`, `DB_USER` and `DB_PASSWORD`. Since `password` is a field created with\nthe option `exclude=True`, it will not be included in the configuration's exported data: that\nguarantees that your password does never leak into `database.yml` on save \u2013 but you may still pass it\nthrough an environment variable (here \u2013 the mentioned `DB_PASSWORD`). Secret files are also supported,\nsee [the pydantic documentation](https://docs.pydantic.dev/latest/usage/settings/#secret-support)\nfor more information.\n\n[pydantic](https://docs.pydantic.dev/latest/) will naturally take care of parsing and validating the loaded data.\nConfiguration models inherit from the `pydantic.BaseSettings` class, so you can use all of its features:\nschema generation, type conversion, validation, etc.\n\nThere are additional features brought to you by _configzen_ worth checking out, though.\n\nYou can use the `db_config` object defined above to access the configuration values:\n\n```python\n>>> db_config.host\nIPv4Address('127.0.0.1')\n```\n\nmodify them, if the pydantic model validation allows\nit ([`<Your model>.Config.validate_assignment`](https://docs.pydantic.dev/latest/usage/model_config/#options) will\nbe `True` by default):\n\n```python\n>>> db_config.host = \"0.0.0.0\"\n>>> db_config.host\nIPv4Address('0.0.0.0')\n```\n\nas well as reload particular values, without touching the rest of the configuration:\n\n```python\n>>> db_config.at(\"port\").reload()\n5432\n>>> db_config\nDatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')\n>>> db_config.at(\"host\").reload()\nIPv4Address('127.0.0.1')\n>>> db_config\nDatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')\n```\n\nor reload the whole configuration:\n\n```python\n>>> db_config.port = 1234\n>>> db_config.reload()\nDatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')\n```\n\nor save a particular value, without touching the rest of the configuration:\n\n```python\n>>> db_config.host = \"0.0.0.0\"\n>>> db_config.port = 443\n>>> db_config\nDatabaseConfig(host=IPv4Address('0.0.0.0'), port=443, user='postgres', password='password')\n>>> db_config.at(\"host\").save()\n40\n>>> db_config.reload()\nDatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')\n```\n\nor save the whole configuration:\n\n```python\n>>> db_config.save()\n39\n```\n\n### Preprocessing\n\nTo see supported preprocessing directives,\nsee [Supported preprocessing directives](#supported-preprocessing-directives).\n\n#### Basic usage\n\nHaving a base configuration file like this (`base.json`):\n\n```json\n{\n \"i18n\": {\n \"language\": \"en\",\n \"timezone\": \"UTC\"\n },\n \"app\": {\n \"debug\": true,\n \"expose\": 8000\n }\n}\n```\n\ncreate another configuration file like this, overriding desired sections as needed:\n\n```yaml\n# production.yml\n^extend: base.json\n\n+app:\n debug: false\n```\n\nand load the `production.yml` configuration file. No explicit changes to the code indicating the use of the `base.json`\nfile are needed.\n\n_Note: Using `+` in front of a key will update the section already defined at that key,\ninstead of overwriting it entirely._\n\nNotice how configuration file formats do not matter in _configzen_: you can\nextend JSON configurations with YAML, but that might be as well any other format\namong the supported ones (see the [Supported file formats](#supported-file-formats) section).\n\nThe above example is equivalent to as if you used:\n\n```yaml\n# production.yml\ni18n:\n language: en\n timezone: UTC\napp:\n debug: false\n expose: 8000\n```\n\nbut with a significant difference: when you save the above configuration, the `^extend` relation to the base\nconfiguration file `base.json` is preserved.\nThis basically means that changes made in the base configuration file will apply to the configuration model instance\nloaded from the `^extend`-ing configuration file.\nAny changes made locally to the model will result in `+` sections being automatically added to the exported\nconfiguration data.\n\n#### Supported preprocessing directives\n\n| Directive | Is the referenced file preprocessed? | Is the directive preserved on export? |\n| ---------- | ------------------------------------ | ------------------------------------- |\n| `^extend` | Yes | Yes |\n| `^include` | Yes | No |\n| `^copy` | No | No |\n\n\n### Interpolation\n\n#### Basic interpolation\n\nYou can use interpolation in your configuration files:\n\n```yaml\ncpu:\n cores: 4\nnum_workers: ${cpu.cores}\n```\n\n```python\n>>> from configzen import ConfigModel\n...\n>>> class CPUConfig(ConfigModel):\n... cores: int\n...\n>>> class AppConfig(ConfigModel):\n... cpu: CPUConfig\n... num_workers: int\n...\n>>> app_config = AppConfig.load(\"app.yml\")\n>>> app_config\nAppConfig(cpu=CPUConfig(cores=4), num_workers=4)\n```\n\n\n#### Reusable configuration with namespaces\n\nYou can share independent configuration models as namespaces through inclusion:\n\n```yaml\n# database.yml\nhost: ${app_config::db_host}\nport: ${app_config::expose}\n```\n\n```yaml\n# app.yml\ndb_host: localhost\nexpose: 8000\n```\n\n```python\n>>> from configzen import ConfigModel, include\n>>> from ipaddress import IPv4Address\n>>>\n>>> @include(\"app_config\")\n... class DatabaseConfig(ConfigModel):\n... host: IPv4Address\n... port: int\n...\n>>> class AppConfig(ConfigModel):\n... db_host: str\n... expose: int\n...\n>>> app_config = AppConfig.load(\"app.yml\")\n>>> app_config\nAppConfig(db_host='localhost', expose=8000)\n>>> db_config = DatabaseConfig.load(\"database.yml\")\n>>> db_config\nDatabaseConfig(host=IPv4Address('127.0.0.1'), port=8000)\n>>> db_config.dict()\n{'host': IPv4Address('127.0.0.1'), 'port': 8000}\n>>> db_config.export() # used when saving\n{'host': '${app_config::db_host}', 'port': '${app_config::expose}'}\n```\n\nYou do not have to pass a variable name to `@include`, though. `@include` lets you overwrite the main interpolation namespace\nor one with a separate name (here: `app_config`) with configuration models, dictionaries and their factories.\n\n\n### Modular configuration\n\n#### Wrapping modules in-place\n\nYou can wrap modules in-place with configuration models:\n\n\n1) Without writing a model class:\n\n```python\n# config.py\nfrom configzen import ConfigModule\n\n# Annotate config fields\nHOST: str = \"localhost\"\nPORT: int = 8000\n\nConfigModule.wrap_this_module()\n```\n\n2) With a model class:\n\n```python\n# config.py\nfrom configzen import ConfigModel\n\n# Annotations are optional\nHOST = \"localhost\"\nPORT = 8000\n\nclass AppConfig(ConfigModel):\n HOST: str\n PORT: int\n\nAppConfig.wrap_this_module()\n```\n\nNow values `HOST` and `PORT` will be validated as `str` and `int` data types, respectively:\n\n```python\n>>> import config # <configuration module 'config' from 'config.py'>\n>>> config.HOST\n'localhost'\n>>> config.PORT\n8000\n>>> config.PORT = \"8000\"\n>>> config.PORT\n8000\n>>> config.PORT = \"abc\"\nTraceback (most recent call last):\n ...\n```\n\n#### Wrapping interchangeable modules\n\nYou can wrap modules outside them with configuration models:\n\n```python\n# setup.py\nfrom configzen import ConfigModel\n\nclass AppConfig(ConfigModel):\n HOST: str = \"localhost\"\n PORT: int = 8000\n\nconfig_model = AppConfig.wrap_module(\"config\")\n```\n\n```py\n# config.py\nHOST: str = \"0.0.0.0\"\nPORT: int = 443\n```\n\n```python\n>>> from setup import config_model\n>>> config_model.HOST\n'0.0.0.0'\n>>> config_model.PORT\n443\n>>> config_model.PORT = \"8000\"\n>>> config_model.PORT\n8000\n>>> import config\n>>> config.HOST\n'0.0.0.0'\n>>> config.PORT\n8000\n```\n\n## Supported file formats\n\n_configzen_ uses [anyconfig](https://pypi.org/project/anyconfig/) to serialize and deserialize data and does not operate on any protocol-specific entities.\nAs an example result, comments in your configuration files are lost on save[^1], but you can exchange file formats without any hassle.\n\nThe following table shows the supported file formats, their requirements, file extensions, and the backend libraries used to accomplish this goal.\n\n| File Format | To use, install: | Recognized File Extension(s) | Backend Library |\n| ----------------------------------------------------------------------------------- | ----------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------- |\n| [JSON](https://en.wikipedia.org/wiki/JSON) | - | `json` | [json](https://docs.python.org/3/library/json.html) (standard library) |\n| [INI](https://en.wikipedia.org/wiki/INI_file) | - | `ini`, `cfg`, `conf` | [configparser](https://docs.python.org/3/library/configparser.html) (standard library) |\n| [TOML](https://en.wikipedia.org/wiki/TOML) | - | `toml` | [toml](https://pypi.python.org/pypi/toml) |\n| [YAML](https://yaml.org) | - | `yaml`, `yml` | [pyyaml](https://pypi.python.org/pypi/PyYAML) / [ruamel.yaml](https://pypi.python.org/pypi/ruamel.yaml) |\n| [XML](https://en.wikipedia.org/wiki/XML) | - | `xml` | [xml](https://docs.python.org/3/library/xml.html) (standard library) |\n| [ConfigObj](https://configobj.readthedocs.io/en/latest/configobj.html#introduction) | `anyconfig-configobj-backend` | `configobj` | [configobj](https://pypi.org/project/configobj/) |\n| [BSON](https://en.wikipedia.org/wiki/BSON) | `anyconfig-bson-backend` | `bson` | [bson](https://pypi.org/project/bson/) |\n| [CBOR](https://cbor.io/) ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)) | `anyconfig-cbor2-backend` | `cbor`, `cbor2` | [cbor2](https://pypi.org/project/cbor2/) |\n| [Amazon Ion](https://en.wikipedia.org/wiki/Ion_(serialization_format)) | `anyconfig-ion-backend` | `ion` | [ion](https://pypi.org/project/amazon.ion/) |\n| CBOR (deprecated, [RFC 7049](https://www.rfc-editor.org/rfc/rfc7049)) | `anyconfig-cbor-backend` | `cbor` | [cbor](https://pypi.org/project/cbor/) |\n| properties | - | `properties` | (native) |\n| shellvars | - | `shellvars` | (native) |\n<!-- Add msgpack when it works -->\nIf your file extension is not recognized, you can register your own file extension by calling `ConfigAgent.register_file_extension(file_extension, parser_name)`.\n\nIf your favorite backend library is not supported, please let me know by reporting it as an issue.\nUsing custom backends is to be supported in the future.\n\n[^1]: A suggested alternative for comments is to use the `description` parameter in your configuration models' fields: `ConfigField(description=...)`.\nThe provided field descriptions are included in JSON schemas generated by the default implementation of the `ConfigModel.schema()` method.\n\n## Setup\n\nIn order to use _configzen_ in your project, install it with your package manager, for example `pip`:\n\n```bash\npip install configzen\n```\n\nIf you are willing to contribute to _configzen_, which is awesome, simply clone this repository and install its\ndependencies with [poetry](https://python-poetry.org/):\n\n```bash\npoetry install --with dev --all-extras\n```\nAfter that, install the [pre-commit](https://pre-commit.com/) hooks:\n\n```bash\npre-commit install --hook-type pre-commit --hook-type pre-push\n```\n\nYou might also need to install required stubs. First, activate your virtual environment:\n\n```bash\npoetry shell\n```\n\nand run (on Linux or [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.3) 7.0+):\n\n```bash\nmypy configzen/ || (echo yes | mypy --install-types)\n```\n\nor, if you are using an older version of PowerShell:\n\n```powershell\nmypy configzen/; if (-not $?) { echo yes | mypy --install-types }\n```\n\n_Note: Using [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) + [pyenv](https://github.com/pyenv/pyenv#readme) (with Python 3.8) for developing configzen is strongly recommended in case you use Windows._\n\nAnd you are good to go. \ud83d\ude80\n\nContributions are welcome! Feel free to [open an issue](https://github.com/bswck/configzen/issues/new/choose) whenever\nyou encounter a bug or have a feature request or [submit a pull request](https://github.com/bswck/configzen/compare) with your changes.\n\n## License\n\n[MIT License](https://choosealicense.com/licenses/mit/)\n\n\n## Credits\n\n* [@Lunarmagpie](https://github.com/Lunarmagpie) for _crucial_ design tips and ideas.\n\n## Author\n\n* [bswck](https://github.com/bswck) (contact: bswck.dev@gmail.com or via [Discord](https://discord.com/) `bswck`)\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "The easiest way to manage configuration files in Python",
"version": "0.10.0",
"project_urls": {
"Homepage": "https://github.com/bswck/configzen"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "50587541b6ecb4c961459e9e4a970d7a1f368e930c2dd6f0e6caf0403f6368f8",
"md5": "76afba7012cff8661992bff13c4f66f1",
"sha256": "bb9b11d21462f50a4400b029b8fe87838907dcb654415cb954a68653ffbbf907"
},
"downloads": -1,
"filename": "configzen-0.10.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "76afba7012cff8661992bff13c4f66f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 41289,
"upload_time": "2023-08-23T21:12:50",
"upload_time_iso_8601": "2023-08-23T21:12:50.146658Z",
"url": "https://files.pythonhosted.org/packages/50/58/7541b6ecb4c961459e9e4a970d7a1f368e930c2dd6f0e6caf0403f6368f8/configzen-0.10.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "718508835a39768c2c60cdef84659b213394f6f7e91bd05ba4c9cf626365a001",
"md5": "98ce7010b592f1f74cec344ebc25d83e",
"sha256": "6bde4b949d21a8fc86ce6c6cd07e5614c299209c1830d13e970830982e74109a"
},
"downloads": -1,
"filename": "configzen-0.10.0.tar.gz",
"has_sig": false,
"md5_digest": "98ce7010b592f1f74cec344ebc25d83e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 42190,
"upload_time": "2023-08-23T21:12:51",
"upload_time_iso_8601": "2023-08-23T21:12:51.568539Z",
"url": "https://files.pythonhosted.org/packages/71/85/08835a39768c2c60cdef84659b213394f6f7e91bd05ba4c9cf626365a001/configzen-0.10.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-23 21:12:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bswck",
"github_project": "configzen",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "configzen"
}