# Dataconf
[![Actions Status](https://github.com/zifeo/dataconf/actions/workflows/test-release.yaml/badge.svg)](https://github.com/zifeo/dataconf/actions)
[![PyPI version](https://badge.fury.io/py/dataconf.svg)](https://badge.fury.io/py/dataconf)
Simple dataclasses configuration management for Python with
hocon/json/yaml/properties/env-vars/dict/cli support.
## Getting started
Requires at least Python 3.9.
```bash
# pypi
pip install dataconf
poetry add dataconf
# remote master
pip install --upgrade git+https://github.com/zifeo/dataconf.git
poetry add git+https://github.com/zifeo/dataconf.git
# local repo/dev
poetry install
pre-commit install
```
## Usage
```python
import os
from dataclasses import dataclass, field
from typing import List, Dict, Text, Union, Tuple
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
import dataconf
conf = """
str_name = test
str_name = ${?HOME}
dash-to-underscore = true
float_num = 2.2
iso_datetime = "2000-01-01T20:00:00"
iso_duration = "P123DT4H5M6S"
variable_length_tuple_data = [
1
2
3
]
tuple_data = [
a
P1D
]
# this is a comment
list_data = [
a
b
]
nested {
a = test
b : 1
}
nested_list = [
{
a = test1
b : 2.5
}
]
duration = 2s
union = 1
people {
name = Thailand
}
zone {
area_code = 42
}
"""
class AbstractBaseClass:
pass
@dataclass
class Person(AbstractBaseClass):
name: Text
@dataclass
class Zone(AbstractBaseClass):
area_code: int
@dataclass
class Nested:
a: Text
b: float
@dataclass
class Config:
str_name: Text
dash_to_underscore: bool
float_num: float
iso_datetime: datetime
iso_duration: timedelta
variable_length_tuple_data: Tuple[int, ...]
tuple_data: Tuple[Text, timedelta]
list_data: List[Text]
nested: Nested
nested_list: List[Nested]
duration: relativedelta
union: Union[Text, int]
people: AbstractBaseClass
zone: AbstractBaseClass
default: Text = 'hello'
default_factory: Dict[Text, Text] = field(default_factory=dict)
print(dataconf.string(conf, Config))
# Config(
# str_name='/users/root/',
# dash_to_underscore=True,
# float_num=2.2,
# iso_datetime=datetime.datetime(2000, 1, 1, 20, 0),
# iso_duration=datetime.timedelta(days=123, seconds=14706),
# variable_length_tuple_data=(1,2,3),
# tuple_data=('a', datetime.timedelta(days=1)),
# list_data=['a', 'b'],
# nested=Nested(a='test', b=1),
# nested_list=[Nested(a='test1', b=2.5)],
# duration=relativedelta(seconds=+2),
# union=1,
# people=Person(name='Thailand'),
# zone=Zone(area_code=42),
# default='hello',
# default_factory={}
# )
@dataclass
class Example:
hello: str
world: str
foo: List[str]
os.environ['DC_WORLD'] = 'monde'
print(
dataconf
.multi
.url('https://raw.githubusercontent.com/zifeo/dataconf/main/confs/simple.hocon')
.env('DC')
.on(Example)
)
# Example(hello='bonjour',world='monde')
```
## API
```python
import dataconf
conf = dataconf.string('{ name: Test }', Config)
conf = dataconf.string('name:\n\tvalue: Test', Config, loader=dataconf.YAML) # dataconf.HOCON by default
conf = dataconf.env('PREFIX_', Config)
conf = dataconf.dict({'name': 'Test'}, Config)
conf = dataconf.url('https://raw.githubusercontent.com/zifeo/dataconf/master/confs/test.hocon', Config) # hocon, json, yaml, properties
conf = dataconf.file('confs/test.hocon', Config) # hocon, json, yaml, properties
conf = dataconf.cli(sys.argv, Config)
# Aggregation
conf = dataconf.multi.string(...).env(...).url(...).file(...).dict(...).cli(...).on(Config)
# Same api as Python json/yaml packages (e.g. `load`, `loads`, `dump`, `dumps`)
conf = dataconf.load('confs/test.hocon', Config) # hocon, json, yaml, properties
conf = dataconf.load('confs/test.yaml', Config, loader=dataconf.YAML) # dataconf.HOCON by default
dataconf.dump('confs/test.hocon', conf, out='hocon')
dataconf.dump('confs/test.json', conf, out='json')
dataconf.dump('confs/test.yaml', conf, out='yaml')
dataconf.dump('confs/test.properties', conf, out='properties')
```
For full HOCON capabilities see
[here](https://github.com/chimpler/pyhocon/#example-of-hocon-file).
## Parse env vars
```bash
PREFIX_VAR=a
PREFIX_VAR_NAME=b
PREFIX_TEST__NAME=c
PREFIX_LS_0=d
PREFIX_LS_1=e
PREFIX_LSLS_0_0=f
PREFIX_LSOB_0__NAME=g
PREFIX_NESTED_="{ name: Test }"
PREFIX_SUB_="{ value: ${PREFIX_VAR} }"
```
is equivalent to
```
{
var = a
var_name = b
test {
name = c
}
ls = [
d
e
]
lsls = [
[
f
]
]
lsob = [
{
name = g
}
]
nested {
# parse nested config by suffixing env var with `_`
name: Test
}
sub {
# will have value "a" at parsing, useful for aliases
value = ${PREFIX_VAR}
}
}
```
Note that when using `.env` source, the strict mode is disabled and value might
be casted.
## Parse CLI arguments
Same as env vars parse (dashes are converted to underscore, e.g. `TEST_A` →
`--test-a`).
## CLI usage
Can be used for validation or converting between supported file formats (`-o`).
```shell
dataconf -c confs/test.hocon -m tests.configs -d TestConf -o hocon
# dataconf.exceptions.TypeConfigException: expected type <class 'datetime.timedelta'> at .duration, got <class 'int'>
```
Raw data
{
"_id": null,
"home_page": "https://github.com/zifeo/dataconf",
"name": "dataconf",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "configuration, dataclasses, yaml, hocon, json, properties, cli, environment variables",
"author": null,
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/c1/b6/a41874c4ebf4e2bb0c49e6b03563cf2503258235fa4affec464db4e7d00e/dataconf-3.3.0.tar.gz",
"platform": null,
"description": "# Dataconf\n\n[![Actions Status](https://github.com/zifeo/dataconf/actions/workflows/test-release.yaml/badge.svg)](https://github.com/zifeo/dataconf/actions)\n[![PyPI version](https://badge.fury.io/py/dataconf.svg)](https://badge.fury.io/py/dataconf)\n\nSimple dataclasses configuration management for Python with\nhocon/json/yaml/properties/env-vars/dict/cli support.\n\n## Getting started\n\nRequires at least Python 3.9.\n\n```bash\n# pypi\npip install dataconf\npoetry add dataconf\n\n# remote master\npip install --upgrade git+https://github.com/zifeo/dataconf.git\npoetry add git+https://github.com/zifeo/dataconf.git\n\n# local repo/dev\npoetry install\npre-commit install\n```\n\n## Usage\n\n```python\nimport os\nfrom dataclasses import dataclass, field\nfrom typing import List, Dict, Text, Union, Tuple\nfrom dateutil.relativedelta import relativedelta\nfrom datetime import datetime, timedelta\nimport dataconf\n\nconf = \"\"\"\nstr_name = test\nstr_name = ${?HOME}\ndash-to-underscore = true\nfloat_num = 2.2\niso_datetime = \"2000-01-01T20:00:00\"\niso_duration = \"P123DT4H5M6S\"\nvariable_length_tuple_data = [\n 1\n 2\n 3\n]\ntuple_data = [\n a\n P1D\n]\n# this is a comment\nlist_data = [\n a\n b\n]\nnested {\n a = test\n b : 1\n}\nnested_list = [\n {\n a = test1\n b : 2.5\n }\n]\nduration = 2s\nunion = 1\npeople {\n name = Thailand\n}\nzone {\n area_code = 42\n}\n\"\"\"\n\nclass AbstractBaseClass:\n pass\n\n@dataclass\nclass Person(AbstractBaseClass):\n name: Text\n\n@dataclass\nclass Zone(AbstractBaseClass):\n area_code: int\n\n@dataclass\nclass Nested:\n a: Text\n b: float\n\n@dataclass\nclass Config:\n str_name: Text\n dash_to_underscore: bool\n float_num: float\n iso_datetime: datetime\n iso_duration: timedelta\n variable_length_tuple_data: Tuple[int, ...]\n tuple_data: Tuple[Text, timedelta]\n list_data: List[Text]\n nested: Nested\n nested_list: List[Nested]\n duration: relativedelta\n union: Union[Text, int]\n people: AbstractBaseClass\n zone: AbstractBaseClass\n default: Text = 'hello'\n default_factory: Dict[Text, Text] = field(default_factory=dict)\n\nprint(dataconf.string(conf, Config))\n# Config(\n# str_name='/users/root/',\n# dash_to_underscore=True,\n# float_num=2.2,\n# iso_datetime=datetime.datetime(2000, 1, 1, 20, 0),\n# iso_duration=datetime.timedelta(days=123, seconds=14706),\n# variable_length_tuple_data=(1,2,3),\n# tuple_data=('a', datetime.timedelta(days=1)),\n# list_data=['a', 'b'],\n# nested=Nested(a='test', b=1),\n# nested_list=[Nested(a='test1', b=2.5)],\n# duration=relativedelta(seconds=+2),\n# union=1,\n# people=Person(name='Thailand'),\n# zone=Zone(area_code=42),\n# default='hello',\n# default_factory={}\n# )\n\n@dataclass\nclass Example:\n hello: str\n world: str\n foo: List[str]\n\nos.environ['DC_WORLD'] = 'monde'\n\nprint(\n dataconf\n .multi\n .url('https://raw.githubusercontent.com/zifeo/dataconf/main/confs/simple.hocon')\n .env('DC')\n .on(Example)\n)\n# Example(hello='bonjour',world='monde')\n```\n\n## API\n\n```python\nimport dataconf\n\nconf = dataconf.string('{ name: Test }', Config)\nconf = dataconf.string('name:\\n\\tvalue: Test', Config, loader=dataconf.YAML) # dataconf.HOCON by default\nconf = dataconf.env('PREFIX_', Config)\nconf = dataconf.dict({'name': 'Test'}, Config)\nconf = dataconf.url('https://raw.githubusercontent.com/zifeo/dataconf/master/confs/test.hocon', Config) # hocon, json, yaml, properties\nconf = dataconf.file('confs/test.hocon', Config) # hocon, json, yaml, properties\nconf = dataconf.cli(sys.argv, Config)\n\n# Aggregation\nconf = dataconf.multi.string(...).env(...).url(...).file(...).dict(...).cli(...).on(Config)\n\n# Same api as Python json/yaml packages (e.g. `load`, `loads`, `dump`, `dumps`)\nconf = dataconf.load('confs/test.hocon', Config) # hocon, json, yaml, properties\nconf = dataconf.load('confs/test.yaml', Config, loader=dataconf.YAML) # dataconf.HOCON by default\ndataconf.dump('confs/test.hocon', conf, out='hocon')\ndataconf.dump('confs/test.json', conf, out='json')\ndataconf.dump('confs/test.yaml', conf, out='yaml')\ndataconf.dump('confs/test.properties', conf, out='properties')\n```\n\nFor full HOCON capabilities see\n[here](https://github.com/chimpler/pyhocon/#example-of-hocon-file).\n\n## Parse env vars\n\n```bash\nPREFIX_VAR=a\nPREFIX_VAR_NAME=b\nPREFIX_TEST__NAME=c\nPREFIX_LS_0=d\nPREFIX_LS_1=e\nPREFIX_LSLS_0_0=f\nPREFIX_LSOB_0__NAME=g\nPREFIX_NESTED_=\"{ name: Test }\"\nPREFIX_SUB_=\"{ value: ${PREFIX_VAR} }\"\n```\n\nis equivalent to\n\n```\n{\n var = a\n var_name = b\n test {\n name = c\n }\n ls = [\n d\n e\n ]\n lsls = [\n [\n f\n ]\n ]\n lsob = [\n {\n name = g\n }\n ]\n nested {\n # parse nested config by suffixing env var with `_`\n name: Test\n }\n sub {\n # will have value \"a\" at parsing, useful for aliases\n value = ${PREFIX_VAR}\n }\n}\n```\n\nNote that when using `.env` source, the strict mode is disabled and value might\nbe casted.\n\n## Parse CLI arguments\n\nSame as env vars parse (dashes are converted to underscore, e.g. `TEST_A` \u2192\n`--test-a`).\n\n## CLI usage\n\nCan be used for validation or converting between supported file formats (`-o`).\n\n```shell\ndataconf -c confs/test.hocon -m tests.configs -d TestConf -o hocon\n# dataconf.exceptions.TypeConfigException: expected type <class 'datetime.timedelta'> at .duration, got <class 'int'>\n```\n",
"bugtrack_url": null,
"license": "MPL-2.0",
"summary": "Simple dataclasses configuration management for Python with hocon/json/yaml/properties/env-vars/dict support.",
"version": "3.3.0",
"project_urls": {
"Homepage": "https://github.com/zifeo/dataconf",
"Repository": "https://github.com/zifeo/dataconf"
},
"split_keywords": [
"configuration",
" dataclasses",
" yaml",
" hocon",
" json",
" properties",
" cli",
" environment variables"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cf4780a04c27f9bb66f7d46a8cd9a49cbb48a894328da47420cc592e2f252d9c",
"md5": "b4676dfc728421ed233fe18e461a41d2",
"sha256": "5f80bc6f5c130f2c3e463ea8cbc57221cf5e789c580e3880e19b284bee25db41"
},
"downloads": -1,
"filename": "dataconf-3.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b4676dfc728421ed233fe18e461a41d2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 16080,
"upload_time": "2024-09-17T06:14:41",
"upload_time_iso_8601": "2024-09-17T06:14:41.543929Z",
"url": "https://files.pythonhosted.org/packages/cf/47/80a04c27f9bb66f7d46a8cd9a49cbb48a894328da47420cc592e2f252d9c/dataconf-3.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c1b6a41874c4ebf4e2bb0c49e6b03563cf2503258235fa4affec464db4e7d00e",
"md5": "1fc0e391dfba792f5b0541fcf580e829",
"sha256": "da656c5e45bae9071a380d991183db98024c13a861e3d8fd225629bd9a76dd6f"
},
"downloads": -1,
"filename": "dataconf-3.3.0.tar.gz",
"has_sig": false,
"md5_digest": "1fc0e391dfba792f5b0541fcf580e829",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 15322,
"upload_time": "2024-09-17T06:14:43",
"upload_time_iso_8601": "2024-09-17T06:14:43.321505Z",
"url": "https://files.pythonhosted.org/packages/c1/b6/a41874c4ebf4e2bb0c49e6b03563cf2503258235fa4affec464db4e7d00e/dataconf-3.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-17 06:14:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "zifeo",
"github_project": "dataconf",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "dataconf"
}