dataconf 2.2.0__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dataconf-2.2.0 → dataconf-2.2.2}/PKG-INFO +3 -3
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/utils.py +33 -23
- dataconf-2.2.2/dataconf/version.py +6 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/pyproject.toml +7 -7
- {dataconf-2.2.0 → dataconf-2.2.2}/setup.py +2 -2
- dataconf-2.2.0/dataconf/version.py +0 -1
- {dataconf-2.2.0 → dataconf-2.2.2}/LICENSE +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/README.md +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/__init__.py +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/cli.py +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/exceptions.py +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/main.py +0 -0
- {dataconf-2.2.0 → dataconf-2.2.2}/dataconf/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dataconf
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Simple dataclasses configuration management for Python with hocon/json/yaml/properties/env-vars/dict support.
|
|
5
5
|
Home-page: https://github.com/zifeo/dataconf
|
|
6
6
|
License: MPL-2.0
|
|
@@ -15,8 +15,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.8
|
|
17
17
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
-
Requires-Dist: PyYAML (>=6.0,<7.0)
|
|
19
|
-
Requires-Dist: pyhocon (==0.3.
|
|
18
|
+
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
|
19
|
+
Requires-Dist: pyhocon (==0.3.59)
|
|
20
20
|
Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
|
|
21
21
|
Project-URL: Repository, https://github.com/zifeo/dataconf
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
@@ -6,6 +6,7 @@ from datetime import datetime
|
|
|
6
6
|
from enum import Enum
|
|
7
7
|
from enum import IntEnum
|
|
8
8
|
from inspect import isclass
|
|
9
|
+
|
|
9
10
|
from typing import Any
|
|
10
11
|
from typing import Dict
|
|
11
12
|
from typing import get_args
|
|
@@ -28,6 +29,12 @@ from pyhocon.config_tree import ConfigList
|
|
|
28
29
|
from pyhocon.config_tree import ConfigTree
|
|
29
30
|
import pyparsing
|
|
30
31
|
|
|
32
|
+
from dataconf.version import PY310up
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if PY310up:
|
|
36
|
+
from types import UnionType
|
|
37
|
+
|
|
31
38
|
|
|
32
39
|
NoneType = type(None)
|
|
33
40
|
|
|
@@ -42,9 +49,13 @@ def __parse_type(value: Any, clazz: Type, path: str, check: bool):
|
|
|
42
49
|
raise TypeConfigException(f"expected type {clazz} at {path}, got {type(value)}")
|
|
43
50
|
|
|
44
51
|
|
|
52
|
+
def is_union(origin):
|
|
53
|
+
return origin is Union or (PY310up and origin is UnionType)
|
|
54
|
+
|
|
55
|
+
|
|
45
56
|
def is_optional(type: Type):
|
|
46
57
|
# Optional = Union[T, NoneType]
|
|
47
|
-
return get_origin(type)
|
|
58
|
+
return is_union(get_origin(type)) and NoneType in get_args(type)
|
|
48
59
|
|
|
49
60
|
|
|
50
61
|
def __parse(value: any, clazz: Type, path: str, strict: bool, ignore_unexpected: bool):
|
|
@@ -68,6 +79,9 @@ def __parse(value: any, clazz: Type, path: str, strict: bool, ignore_unexpected:
|
|
|
68
79
|
val = f.default_factory()
|
|
69
80
|
else:
|
|
70
81
|
val = f.default
|
|
82
|
+
if is_dataclass(val):
|
|
83
|
+
# if val is a dataclass, convert to ConfigTree
|
|
84
|
+
val = ConfigTree(asdict(val))
|
|
71
85
|
|
|
72
86
|
if not isinstance(val, _MISSING_TYPE):
|
|
73
87
|
fs[f.name] = __parse(
|
|
@@ -120,33 +134,29 @@ def __parse(value: any, clazz: Type, path: str, strict: bool, ignore_unexpected:
|
|
|
120
134
|
}
|
|
121
135
|
return None
|
|
122
136
|
|
|
123
|
-
if
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return __parse(
|
|
127
|
-
value,
|
|
128
|
-
left if right is NoneType else right,
|
|
129
|
-
path,
|
|
130
|
-
strict,
|
|
131
|
-
ignore_unexpected,
|
|
132
|
-
)
|
|
133
|
-
except TypeConfigException:
|
|
134
|
-
# cannot parse Optional
|
|
135
|
-
return None
|
|
136
|
-
|
|
137
|
-
if origin is Union:
|
|
137
|
+
if is_union(origin):
|
|
138
|
+
# Optional = Union[T, NoneType]
|
|
139
|
+
has_none = False
|
|
138
140
|
for parse_candidate in args:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
if parse_candidate is NoneType:
|
|
142
|
+
has_none = True
|
|
143
|
+
else:
|
|
144
|
+
try:
|
|
145
|
+
return __parse(
|
|
146
|
+
value, parse_candidate, path, strict, ignore_unexpected
|
|
147
|
+
)
|
|
148
|
+
except TypeConfigException:
|
|
149
|
+
continue
|
|
150
|
+
|
|
151
|
+
if has_none:
|
|
152
|
+
return None
|
|
143
153
|
|
|
144
154
|
raise TypeConfigException(
|
|
145
155
|
f"expected one of {', '.join(map(str, args))} at {path}, got {type(value)}"
|
|
146
156
|
)
|
|
147
157
|
|
|
148
158
|
if clazz is bool:
|
|
149
|
-
if not strict:
|
|
159
|
+
if not strict and value is not None:
|
|
150
160
|
try:
|
|
151
161
|
value = bool(value)
|
|
152
162
|
except ValueError:
|
|
@@ -154,7 +164,7 @@ def __parse(value: any, clazz: Type, path: str, strict: bool, ignore_unexpected:
|
|
|
154
164
|
return __parse_type(value, clazz, path, isinstance(value, bool))
|
|
155
165
|
|
|
156
166
|
if clazz is int:
|
|
157
|
-
if not strict:
|
|
167
|
+
if not strict and value is not None:
|
|
158
168
|
try:
|
|
159
169
|
value = int(value)
|
|
160
170
|
except ValueError:
|
|
@@ -162,7 +172,7 @@ def __parse(value: any, clazz: Type, path: str, strict: bool, ignore_unexpected:
|
|
|
162
172
|
return __parse_type(value, clazz, path, isinstance(value, int))
|
|
163
173
|
|
|
164
174
|
if clazz is float:
|
|
165
|
-
if not strict:
|
|
175
|
+
if not strict and value is not None:
|
|
166
176
|
try:
|
|
167
177
|
value = float(value)
|
|
168
178
|
except ValueError:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dataconf"
|
|
3
|
-
version = "2.2.
|
|
3
|
+
version = "2.2.2"
|
|
4
4
|
description = "Simple dataclasses configuration management for Python with hocon/json/yaml/properties/env-vars/dict support."
|
|
5
5
|
authors = []
|
|
6
6
|
license = "MPL-2.0"
|
|
@@ -30,20 +30,20 @@ dataconf = 'dataconf.cli:run'
|
|
|
30
30
|
|
|
31
31
|
[tool.poetry.dependencies]
|
|
32
32
|
python = "^3.8"
|
|
33
|
-
pyhocon = "0.3.
|
|
33
|
+
pyhocon = "0.3.59"
|
|
34
34
|
python-dateutil = "^2.8.2"
|
|
35
|
-
PyYAML = "^6.0"
|
|
35
|
+
PyYAML = "^6.0.1"
|
|
36
36
|
|
|
37
37
|
[tool.poetry.group.dev.dependencies]
|
|
38
|
-
pytest = "^7.
|
|
38
|
+
pytest = "^7.4.2"
|
|
39
39
|
pre-commit = ">=2.21,<4.0"
|
|
40
40
|
commitizen = ">=2.42.1,<4.0.0"
|
|
41
|
-
pytest-httpserver = "^1.0.
|
|
42
|
-
ruff = ">=0.0.247,<0.0.
|
|
41
|
+
pytest-httpserver = "^1.0.8"
|
|
42
|
+
ruff = ">=0.0.247,<0.0.287"
|
|
43
43
|
|
|
44
44
|
[tool.commitizen]
|
|
45
45
|
name = "cz_conventional_commits"
|
|
46
|
-
version = "2.2.
|
|
46
|
+
version = "2.2.2"
|
|
47
47
|
tag_format = "v$major.$minor.$patch$prerelease"
|
|
48
48
|
version_files = [
|
|
49
49
|
"pyproject.toml:version",
|
|
@@ -8,14 +8,14 @@ package_data = \
|
|
|
8
8
|
{'': ['*']}
|
|
9
9
|
|
|
10
10
|
install_requires = \
|
|
11
|
-
['PyYAML>=6.0,<7.0', 'pyhocon==0.3.
|
|
11
|
+
['PyYAML>=6.0.1,<7.0.0', 'pyhocon==0.3.59', 'python-dateutil>=2.8.2,<3.0.0']
|
|
12
12
|
|
|
13
13
|
entry_points = \
|
|
14
14
|
{'console_scripts': ['dataconf = dataconf.cli:run']}
|
|
15
15
|
|
|
16
16
|
setup_kwargs = {
|
|
17
17
|
'name': 'dataconf',
|
|
18
|
-
'version': '2.2.
|
|
18
|
+
'version': '2.2.2',
|
|
19
19
|
'description': 'Simple dataclasses configuration management for Python with hocon/json/yaml/properties/env-vars/dict support.',
|
|
20
20
|
'long_description': '# Dataconf\n\n[](https://github.com/zifeo/dataconf/actions)\n[](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.8.\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\nfrom dateutil.relativedelta import relativedelta\nfrom datetime import datetime\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"\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 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# list_data=[\'a\', \'b\'],\n# nested=Nested(a=\'test\'),\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` →\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',
|
|
21
21
|
'author': 'None',
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|