python-simpleconf 0.8.2__tar.gz → 0.9.0__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.
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/PKG-INFO +41 -1
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/README.md +35 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/pyproject.toml +6 -1
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/__init__.py +1 -1
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/__init__.py +26 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/env.py +19 -2
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/ini.py +19 -4
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/json.py +19 -2
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/toml.py +22 -4
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/yaml.py +20 -2
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/utils.py +56 -1
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/LICENSE +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/caster.py +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/config.py +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/exceptions.py +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/dict.py +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/loaders/osenv.py +0 -0
- {python_simpleconf-0.8.2 → python_simpleconf-0.9.0}/simpleconf/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-simpleconf
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Simple configuration management with python.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,11 +19,16 @@ Provides-Extra: all
|
|
|
19
19
|
Provides-Extra: async
|
|
20
20
|
Provides-Extra: env
|
|
21
21
|
Provides-Extra: ini
|
|
22
|
+
Provides-Extra: jinja2
|
|
23
|
+
Provides-Extra: liquid
|
|
24
|
+
Provides-Extra: liquidpy
|
|
22
25
|
Provides-Extra: toml
|
|
23
26
|
Provides-Extra: yaml
|
|
24
27
|
Requires-Dist: aiofiles (>=23.0.0) ; extra == "async"
|
|
25
28
|
Requires-Dist: diot (>=0.3.2,<0.4.0)
|
|
26
29
|
Requires-Dist: iniconfig (>=2.0,<3.0) ; extra == "ini" or extra == "all"
|
|
30
|
+
Requires-Dist: jinja2 (>=3.0,<4.0) ; extra == "jinja2"
|
|
31
|
+
Requires-Dist: liquidpy (>=0.8,<0.9) ; extra == "liquid" or extra == "liquidpy"
|
|
27
32
|
Requires-Dist: panpath (>=0.4.8,<0.5.0)
|
|
28
33
|
Requires-Dist: python-dotenv (>=1.1,<2.0) ; extra == "env" or extra == "all"
|
|
29
34
|
Requires-Dist: pyyaml (>=6,<7) ; extra == "yaml" or extra == "all"
|
|
@@ -64,6 +69,7 @@ pip install python-simpleconf[all]
|
|
|
64
69
|
- Profile support
|
|
65
70
|
- Simple APIs
|
|
66
71
|
- Async loading support
|
|
72
|
+
- Templated configuration files support (jinja2 and liquid)
|
|
67
73
|
|
|
68
74
|
## Usage
|
|
69
75
|
|
|
@@ -311,3 +317,37 @@ Values are casted by `ast.literal_eval()`.
|
|
|
311
317
|
|
|
312
318
|
`@toml:a = 1` -> `{"a": 1}`
|
|
313
319
|
|
|
320
|
+
### Templated configuration files
|
|
321
|
+
|
|
322
|
+
`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.
|
|
323
|
+
|
|
324
|
+
`config.toml.j2`
|
|
325
|
+
|
|
326
|
+
```toml
|
|
327
|
+
a = {{ 1 + 2 }}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from simpleconf import Config
|
|
332
|
+
|
|
333
|
+
conf = Config.load('config.toml.j2')
|
|
334
|
+
# conf.a == 3
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
`config.liq.toml`
|
|
338
|
+
|
|
339
|
+
```toml
|
|
340
|
+
{% for i in range(1, 3) %}
|
|
341
|
+
[section{{i}}]
|
|
342
|
+
a = {{i}}
|
|
343
|
+
{% endfor %}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
from simpleconf import Config
|
|
348
|
+
|
|
349
|
+
conf = Config.load('config.liq.toml')
|
|
350
|
+
# conf.section1.a == 1
|
|
351
|
+
# conf.section2.a == 2
|
|
352
|
+
```
|
|
353
|
+
|
|
@@ -29,6 +29,7 @@ pip install python-simpleconf[all]
|
|
|
29
29
|
- Profile support
|
|
30
30
|
- Simple APIs
|
|
31
31
|
- Async loading support
|
|
32
|
+
- Templated configuration files support (jinja2 and liquid)
|
|
32
33
|
|
|
33
34
|
## Usage
|
|
34
35
|
|
|
@@ -275,3 +276,37 @@ Values are casted by `ast.literal_eval()`.
|
|
|
275
276
|
#### TOML caster
|
|
276
277
|
|
|
277
278
|
`@toml:a = 1` -> `{"a": 1}`
|
|
279
|
+
|
|
280
|
+
### Templated configuration files
|
|
281
|
+
|
|
282
|
+
`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.
|
|
283
|
+
|
|
284
|
+
`config.toml.j2`
|
|
285
|
+
|
|
286
|
+
```toml
|
|
287
|
+
a = {{ 1 + 2 }}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from simpleconf import Config
|
|
292
|
+
|
|
293
|
+
conf = Config.load('config.toml.j2')
|
|
294
|
+
# conf.a == 3
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`config.liq.toml`
|
|
298
|
+
|
|
299
|
+
```toml
|
|
300
|
+
{% for i in range(1, 3) %}
|
|
301
|
+
[section{{i}}]
|
|
302
|
+
a = {{i}}
|
|
303
|
+
{% endfor %}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
from simpleconf import Config
|
|
308
|
+
|
|
309
|
+
conf = Config.load('config.liq.toml')
|
|
310
|
+
# conf.section1.a == 1
|
|
311
|
+
# conf.section2.a == 2
|
|
312
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "python-simpleconf"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.9.0"
|
|
8
8
|
description = "Simple configuration management with python."
|
|
9
9
|
authors = [ "pwwang <pwwang@pwwang.com>",]
|
|
10
10
|
license = "MIT"
|
|
@@ -26,6 +26,8 @@ rtoml = {version = "^0.12", optional = true, platform = "linux"}
|
|
|
26
26
|
tomli = {version = "^2.0", optional = true, markers = 'sys_platform != "linux"'}
|
|
27
27
|
iniconfig = {version = "^2.0", optional = true}
|
|
28
28
|
aiofiles = {version = ">=23.0.0", optional = true}
|
|
29
|
+
jinja2 = {version = "^3.0", optional = true}
|
|
30
|
+
liquidpy = {version = "^0.8", optional = true}
|
|
29
31
|
|
|
30
32
|
[tool.poetry.extras]
|
|
31
33
|
ini = [ "iniconfig" ]
|
|
@@ -33,6 +35,9 @@ env = [ "python-dotenv"]
|
|
|
33
35
|
yaml = [ "pyyaml"]
|
|
34
36
|
toml = [ "rtoml", "tomli"]
|
|
35
37
|
async = [ "aiofiles"]
|
|
38
|
+
jinja2 = [ "jinja2"]
|
|
39
|
+
liquid = [ "liquidpy"]
|
|
40
|
+
liquidpy = [ "liquidpy"]
|
|
36
41
|
all = [ "iniconfig", "python-dotenv", "pyyaml", "rtoml", "tomli"]
|
|
37
42
|
|
|
38
43
|
[tool.poetry.group.dev.dependencies]
|
|
@@ -132,3 +132,29 @@ class NoConvertingPathMixin(ABC):
|
|
|
132
132
|
async def a_loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
133
133
|
"""Asynchronously load the configuration from a toml file"""
|
|
134
134
|
return self.loading(conf, ignore_nonexist) # type: ignore[attr-defined]
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class LoaderModifierMixin(ABC):
|
|
138
|
+
"""Loader mixin class with content modifier"""
|
|
139
|
+
|
|
140
|
+
def _modifier(self, content: str | bytes) -> str | bytes:
|
|
141
|
+
"""Modify the content of the configuration file before loading"""
|
|
142
|
+
return content
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class J2ModifierMixin(LoaderModifierMixin):
|
|
146
|
+
"""Loader mixin class with Jinja2 content modifier"""
|
|
147
|
+
|
|
148
|
+
def _modifier(self, content: str | bytes) -> str | bytes:
|
|
149
|
+
"""Modify the content of the configuration file before loading"""
|
|
150
|
+
from jinja2 import Template
|
|
151
|
+
return Template(content).render()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class LiqModifierMixin(LoaderModifierMixin):
|
|
155
|
+
"""Loader mixin class with Liquid content modifier"""
|
|
156
|
+
|
|
157
|
+
def _modifier(self, content: str | bytes) -> str | bytes:
|
|
158
|
+
"""Modify the content of the configuration file before loading"""
|
|
159
|
+
from liquid import Liquid
|
|
160
|
+
return Liquid(content, from_file=False, mode="wild").render()
|
|
@@ -16,12 +16,18 @@ from ..caster import (
|
|
|
16
16
|
json_caster,
|
|
17
17
|
toml_caster,
|
|
18
18
|
)
|
|
19
|
-
from . import
|
|
19
|
+
from . import (
|
|
20
|
+
Loader,
|
|
21
|
+
NoConvertingPathMixin,
|
|
22
|
+
LoaderModifierMixin,
|
|
23
|
+
J2ModifierMixin,
|
|
24
|
+
LiqModifierMixin,
|
|
25
|
+
)
|
|
20
26
|
|
|
21
27
|
dotenv = require_package("dotenv")
|
|
22
28
|
|
|
23
29
|
|
|
24
|
-
class EnvLoader(Loader):
|
|
30
|
+
class EnvLoader(Loader, LoaderModifierMixin):
|
|
25
31
|
"""Env file loader"""
|
|
26
32
|
|
|
27
33
|
CASTERS = [
|
|
@@ -46,6 +52,7 @@ class EnvLoader(Loader):
|
|
|
46
52
|
|
|
47
53
|
conf = self.__class__._convert_path(conf)
|
|
48
54
|
content = conf.read_text() # so that cloud paths work
|
|
55
|
+
content = self._modifier(content)
|
|
49
56
|
return dotenv.dotenv_values(stream=io.StringIO(content))
|
|
50
57
|
|
|
51
58
|
async def a_loading(self, conf, ignore_nonexist):
|
|
@@ -56,6 +63,7 @@ class EnvLoader(Loader):
|
|
|
56
63
|
content = await content
|
|
57
64
|
if isinstance(content, bytes):
|
|
58
65
|
content = content.decode()
|
|
66
|
+
content = self._modifier(content)
|
|
59
67
|
return dotenv.dotenv_values(stream=io.StringIO(content))
|
|
60
68
|
|
|
61
69
|
if not await self._a_exists(conf, ignore_nonexist):
|
|
@@ -63,6 +71,7 @@ class EnvLoader(Loader):
|
|
|
63
71
|
|
|
64
72
|
conf = self.__class__._convert_path(conf)
|
|
65
73
|
content = await conf.a_read_text() # so that cloud paths work
|
|
74
|
+
content = self._modifier(content)
|
|
66
75
|
return dotenv.dotenv_values(stream=io.StringIO(content))
|
|
67
76
|
|
|
68
77
|
@classmethod
|
|
@@ -89,3 +98,11 @@ class EnvsLoader(NoConvertingPathMixin, EnvLoader): # type: ignore[misc]
|
|
|
89
98
|
def loading(self, conf: Any, ignore_nonexist: bool = False) -> Dict[str, Any]:
|
|
90
99
|
"""Load the configuration from a .env file"""
|
|
91
100
|
return dotenv.dotenv_values(stream=io.StringIO(conf))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class EnvJ2Loader(EnvLoader, J2ModifierMixin):
|
|
104
|
+
"""Env file loader with Jinja2 support"""
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class EnvLiqLoader(EnvLoader, LiqModifierMixin):
|
|
108
|
+
"""Env file loader with Liquid support"""
|
|
@@ -17,12 +17,18 @@ from ..caster import (
|
|
|
17
17
|
json_caster,
|
|
18
18
|
toml_caster,
|
|
19
19
|
)
|
|
20
|
-
from . import
|
|
20
|
+
from . import (
|
|
21
|
+
Loader,
|
|
22
|
+
NoConvertingPathMixin,
|
|
23
|
+
LoaderModifierMixin,
|
|
24
|
+
J2ModifierMixin,
|
|
25
|
+
LiqModifierMixin,
|
|
26
|
+
)
|
|
21
27
|
|
|
22
28
|
iniconfig = require_package("iniconfig")
|
|
23
29
|
|
|
24
30
|
|
|
25
|
-
class IniLoader(Loader):
|
|
31
|
+
class IniLoader(Loader, LoaderModifierMixin):
|
|
26
32
|
"""Ini-like file loader"""
|
|
27
33
|
|
|
28
34
|
CASTERS = [
|
|
@@ -47,7 +53,7 @@ class IniLoader(Loader):
|
|
|
47
53
|
|
|
48
54
|
conf = self.__class__._convert_path(conf)
|
|
49
55
|
content = conf.read_text()
|
|
50
|
-
|
|
56
|
+
content = self._modifier(content)
|
|
51
57
|
return iniconfig.IniConfig(conf, content).sections
|
|
52
58
|
|
|
53
59
|
async def a_loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
@@ -58,6 +64,7 @@ class IniLoader(Loader):
|
|
|
58
64
|
content = await content
|
|
59
65
|
if isinstance(content, bytes):
|
|
60
66
|
content = content.decode()
|
|
67
|
+
content = self._modifier(content)
|
|
61
68
|
return iniconfig.IniConfig("<config>", content).sections
|
|
62
69
|
|
|
63
70
|
if not await self._a_exists(conf, ignore_nonexist):
|
|
@@ -65,7 +72,7 @@ class IniLoader(Loader):
|
|
|
65
72
|
|
|
66
73
|
conf = self.__class__._convert_path(conf)
|
|
67
74
|
content = await conf.a_read_text()
|
|
68
|
-
|
|
75
|
+
content = self._modifier(content)
|
|
69
76
|
return iniconfig.IniConfig(conf, content).sections
|
|
70
77
|
|
|
71
78
|
@classmethod
|
|
@@ -112,3 +119,11 @@ class InisLoader(NoConvertingPathMixin, IniLoader): # type: ignore[misc]
|
|
|
112
119
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
113
120
|
"""Load the configuration from an ini-like file"""
|
|
114
121
|
return iniconfig.IniConfig("<config>", conf).sections
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class IniJ2Loader(IniLoader, J2ModifierMixin):
|
|
125
|
+
"""Ini-like file loader with Jinja2 support"""
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class IniLiqLoader(IniLoader, LiqModifierMixin):
|
|
129
|
+
"""Ini-like file loader with Liquid support"""
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any, Awaitable, Dict
|
|
3
3
|
|
|
4
|
-
from . import
|
|
4
|
+
from . import (
|
|
5
|
+
Loader,
|
|
6
|
+
NoConvertingPathMixin,
|
|
7
|
+
LoaderModifierMixin,
|
|
8
|
+
J2ModifierMixin,
|
|
9
|
+
LiqModifierMixin,
|
|
10
|
+
)
|
|
5
11
|
|
|
6
12
|
|
|
7
|
-
class JsonLoader(Loader):
|
|
13
|
+
class JsonLoader(Loader, LoaderModifierMixin):
|
|
8
14
|
"""Json file loader"""
|
|
9
15
|
|
|
10
16
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
@@ -18,6 +24,7 @@ class JsonLoader(Loader):
|
|
|
18
24
|
|
|
19
25
|
conf = self.__class__._convert_path(conf)
|
|
20
26
|
content = conf.read_text()
|
|
27
|
+
content = self._modifier(content)
|
|
21
28
|
return json.loads(content)
|
|
22
29
|
|
|
23
30
|
async def a_loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
@@ -28,6 +35,7 @@ class JsonLoader(Loader):
|
|
|
28
35
|
content = await content
|
|
29
36
|
if isinstance(content, bytes):
|
|
30
37
|
content = content.decode()
|
|
38
|
+
content = self._modifier(content)
|
|
31
39
|
return json.loads(content)
|
|
32
40
|
|
|
33
41
|
if not await self._a_exists(conf, ignore_nonexist):
|
|
@@ -35,6 +43,7 @@ class JsonLoader(Loader):
|
|
|
35
43
|
|
|
36
44
|
conf = self.__class__._convert_path(conf)
|
|
37
45
|
content = await conf.a_read_text()
|
|
46
|
+
content = self._modifier(content)
|
|
38
47
|
return json.loads(content)
|
|
39
48
|
|
|
40
49
|
|
|
@@ -44,3 +53,11 @@ class JsonsLoader(NoConvertingPathMixin, JsonLoader): # type: ignore[misc]
|
|
|
44
53
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
45
54
|
"""Load the configuration from a json file"""
|
|
46
55
|
return json.loads(conf)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class JsonJ2Loader(JsonLoader, J2ModifierMixin):
|
|
59
|
+
"""Json file loader with Jinja2 support"""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class JsonLiqLoader(JsonLoader, LiqModifierMixin):
|
|
63
|
+
"""Json file loader with Liquid support"""
|
|
@@ -5,12 +5,18 @@ from ..caster import (
|
|
|
5
5
|
none_caster,
|
|
6
6
|
null_caster,
|
|
7
7
|
)
|
|
8
|
-
from . import
|
|
8
|
+
from . import (
|
|
9
|
+
Loader,
|
|
10
|
+
NoConvertingPathMixin,
|
|
11
|
+
LoaderModifierMixin,
|
|
12
|
+
J2ModifierMixin,
|
|
13
|
+
LiqModifierMixin,
|
|
14
|
+
)
|
|
9
15
|
|
|
10
16
|
toml = require_package("rtoml", "tomllib", "tomli")
|
|
11
17
|
|
|
12
18
|
|
|
13
|
-
class TomlLoader(Loader):
|
|
19
|
+
class TomlLoader(Loader, LoaderModifierMixin):
|
|
14
20
|
"""Toml file loader"""
|
|
15
21
|
|
|
16
22
|
CASTERS = [
|
|
@@ -22,6 +28,7 @@ class TomlLoader(Loader):
|
|
|
22
28
|
"""Load the configuration from a toml file"""
|
|
23
29
|
if hasattr(conf, "read"):
|
|
24
30
|
content = conf.read()
|
|
31
|
+
content = self._modifier(content)
|
|
25
32
|
return toml.loads(content)
|
|
26
33
|
|
|
27
34
|
if not self._exists(conf, ignore_nonexist):
|
|
@@ -30,9 +37,10 @@ class TomlLoader(Loader):
|
|
|
30
37
|
conf = self.__class__._convert_path(conf)
|
|
31
38
|
content = conf.read_bytes()
|
|
32
39
|
try:
|
|
33
|
-
return toml.loads(content)
|
|
34
|
-
except TypeError
|
|
40
|
+
return toml.loads(self._modifier(content))
|
|
41
|
+
except Exception: # TypeError, TomlParsingError
|
|
35
42
|
content = content.decode()
|
|
43
|
+
content = self._modifier(content)
|
|
36
44
|
return toml.loads(content)
|
|
37
45
|
|
|
38
46
|
async def a_loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
@@ -43,6 +51,7 @@ class TomlLoader(Loader):
|
|
|
43
51
|
content = await content
|
|
44
52
|
if isinstance(content, bytes):
|
|
45
53
|
content = content.decode()
|
|
54
|
+
content = self._modifier(content)
|
|
46
55
|
return toml.loads(content)
|
|
47
56
|
|
|
48
57
|
if not await self._a_exists(conf, ignore_nonexist):
|
|
@@ -50,6 +59,7 @@ class TomlLoader(Loader):
|
|
|
50
59
|
|
|
51
60
|
conf = self.__class__._convert_path(conf)
|
|
52
61
|
content = await conf.a_read_bytes()
|
|
62
|
+
content = self._modifier(content)
|
|
53
63
|
try:
|
|
54
64
|
return toml.loads(content)
|
|
55
65
|
except TypeError:
|
|
@@ -63,3 +73,11 @@ class TomlsLoader(NoConvertingPathMixin, TomlLoader): # type: ignore[misc]
|
|
|
63
73
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
64
74
|
"""Load the configuration from a toml file"""
|
|
65
75
|
return toml.loads(conf)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class TomlJ2Loader(TomlLoader, J2ModifierMixin):
|
|
79
|
+
"""Toml file loader with Jinja2 support"""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class TomlLiqLoader(TomlLoader, LiqModifierMixin):
|
|
83
|
+
"""Toml file loader with Liquid support"""
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
from typing import Any, Dict, Awaitable
|
|
2
2
|
|
|
3
|
-
from . import
|
|
3
|
+
from . import (
|
|
4
|
+
Loader,
|
|
5
|
+
NoConvertingPathMixin,
|
|
6
|
+
LoaderModifierMixin,
|
|
7
|
+
J2ModifierMixin,
|
|
8
|
+
LiqModifierMixin,
|
|
9
|
+
)
|
|
4
10
|
from ..utils import require_package
|
|
5
11
|
|
|
6
12
|
yaml = require_package("yaml")
|
|
7
13
|
|
|
8
14
|
|
|
9
|
-
class YamlLoader(Loader):
|
|
15
|
+
class YamlLoader(Loader, LoaderModifierMixin):
|
|
10
16
|
"""Yaml file loader"""
|
|
11
17
|
|
|
12
18
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
13
19
|
"""Load the configuration from a yaml file"""
|
|
14
20
|
if hasattr(conf, "read"):
|
|
15
21
|
content = conf.read()
|
|
22
|
+
content = self._modifier(content)
|
|
16
23
|
return yaml.load(content, Loader=yaml.FullLoader)
|
|
17
24
|
|
|
18
25
|
if not self._exists(conf, ignore_nonexist):
|
|
@@ -20,6 +27,7 @@ class YamlLoader(Loader):
|
|
|
20
27
|
|
|
21
28
|
conf = self.__class__._convert_path(conf)
|
|
22
29
|
content = conf.read_text()
|
|
30
|
+
content = self._modifier(content)
|
|
23
31
|
return yaml.load(content, Loader=yaml.FullLoader)
|
|
24
32
|
|
|
25
33
|
async def a_loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
@@ -30,6 +38,7 @@ class YamlLoader(Loader):
|
|
|
30
38
|
content = await content
|
|
31
39
|
if isinstance(content, bytes):
|
|
32
40
|
content = content.decode()
|
|
41
|
+
content = self._modifier(content)
|
|
33
42
|
return yaml.load(content, Loader=yaml.FullLoader)
|
|
34
43
|
|
|
35
44
|
if not await self._a_exists(conf, ignore_nonexist):
|
|
@@ -37,6 +46,7 @@ class YamlLoader(Loader):
|
|
|
37
46
|
|
|
38
47
|
conf = self.__class__._convert_path(conf)
|
|
39
48
|
content = await conf.a_read_text()
|
|
49
|
+
content = self._modifier(content)
|
|
40
50
|
return yaml.load(content, Loader=yaml.FullLoader)
|
|
41
51
|
|
|
42
52
|
|
|
@@ -46,3 +56,11 @@ class YamlsLoader(NoConvertingPathMixin, YamlLoader): # type: ignore[misc]
|
|
|
46
56
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
47
57
|
"""Load the configuration from a yaml file"""
|
|
48
58
|
return yaml.load(conf, Loader=yaml.FullLoader)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class YamlJ2Loader(YamlLoader, J2ModifierMixin):
|
|
62
|
+
"""Yaml file loader with Jinja2 support"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class YamlLiqLoader(YamlLoader, LiqModifierMixin):
|
|
66
|
+
"""Yaml file loader with Liquid support"""
|
|
@@ -12,13 +12,28 @@ POOL_KEY = "_SIMPLECONF_POOL"
|
|
|
12
12
|
META_KEY = "_SIMPLECONF_META"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def config_to_ext(conf: Any) -> str:
|
|
15
|
+
def config_to_ext(conf: Any, secondary: bool = True) -> str:
|
|
16
16
|
"""Find the extension(flag) of the configuration"""
|
|
17
17
|
if isinstance(conf, dict):
|
|
18
18
|
return "dict"
|
|
19
19
|
|
|
20
20
|
conf = Path(conf)
|
|
21
21
|
out = conf.suffix.lstrip(".").lower()
|
|
22
|
+
if out in ('j2', 'jinja2', 'jinja'):
|
|
23
|
+
# x.toml.j2
|
|
24
|
+
return config_to_ext(conf.stem) + '.j2'
|
|
25
|
+
if out in ('liq', 'liquid'):
|
|
26
|
+
# x.toml.liq
|
|
27
|
+
return config_to_ext(conf.stem) + '.liq'
|
|
28
|
+
|
|
29
|
+
if secondary:
|
|
30
|
+
secondary_suffix = conf.with_suffix("").suffix.lstrip(".").lower()
|
|
31
|
+
# x.j2.toml
|
|
32
|
+
if secondary_suffix in ('j2', 'jinja2', 'jinja'):
|
|
33
|
+
return config_to_ext(conf, secondary=False) + '.j2'
|
|
34
|
+
if secondary_suffix in ('liq', 'liquid'):
|
|
35
|
+
return config_to_ext(conf, secondary=False) + '.liq'
|
|
36
|
+
|
|
22
37
|
if not out and conf.name.lower().endswith("rc"):
|
|
23
38
|
out = "rc"
|
|
24
39
|
|
|
@@ -48,6 +63,14 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
48
63
|
from .loaders.env import EnvLoader
|
|
49
64
|
return EnvLoader()
|
|
50
65
|
|
|
66
|
+
if ext == "env.j2":
|
|
67
|
+
from .loaders.env import EnvJ2Loader
|
|
68
|
+
return EnvJ2Loader()
|
|
69
|
+
|
|
70
|
+
if ext == "env.liq":
|
|
71
|
+
from .loaders.env import EnvLiqLoader
|
|
72
|
+
return EnvLiqLoader()
|
|
73
|
+
|
|
51
74
|
if ext == "envs":
|
|
52
75
|
from .loaders.env import EnvsLoader
|
|
53
76
|
return EnvsLoader()
|
|
@@ -56,6 +79,14 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
56
79
|
from .loaders.ini import IniLoader
|
|
57
80
|
return IniLoader()
|
|
58
81
|
|
|
82
|
+
if ext == "ini.j2":
|
|
83
|
+
from .loaders.ini import IniJ2Loader
|
|
84
|
+
return IniJ2Loader()
|
|
85
|
+
|
|
86
|
+
if ext == "ini.liq":
|
|
87
|
+
from .loaders.ini import IniLiqLoader
|
|
88
|
+
return IniLiqLoader()
|
|
89
|
+
|
|
59
90
|
if ext == "inis":
|
|
60
91
|
from .loaders.ini import InisLoader
|
|
61
92
|
return InisLoader()
|
|
@@ -64,6 +95,14 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
64
95
|
from .loaders.json import JsonLoader
|
|
65
96
|
return JsonLoader()
|
|
66
97
|
|
|
98
|
+
if ext == "json.j2":
|
|
99
|
+
from .loaders.json import JsonJ2Loader
|
|
100
|
+
return JsonJ2Loader()
|
|
101
|
+
|
|
102
|
+
if ext == "json.liq":
|
|
103
|
+
from .loaders.json import JsonLiqLoader
|
|
104
|
+
return JsonLiqLoader()
|
|
105
|
+
|
|
67
106
|
if ext == "jsons":
|
|
68
107
|
from .loaders.json import JsonsLoader
|
|
69
108
|
return JsonsLoader()
|
|
@@ -76,6 +115,14 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
76
115
|
from .loaders.toml import TomlLoader
|
|
77
116
|
return TomlLoader()
|
|
78
117
|
|
|
118
|
+
if ext == "toml.j2":
|
|
119
|
+
from .loaders.toml import TomlJ2Loader
|
|
120
|
+
return TomlJ2Loader()
|
|
121
|
+
|
|
122
|
+
if ext == "toml.liq":
|
|
123
|
+
from .loaders.toml import TomlLiqLoader
|
|
124
|
+
return TomlLiqLoader()
|
|
125
|
+
|
|
79
126
|
if ext == "tomls":
|
|
80
127
|
from .loaders.toml import TomlsLoader
|
|
81
128
|
return TomlsLoader()
|
|
@@ -84,6 +131,14 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
84
131
|
from .loaders.yaml import YamlLoader
|
|
85
132
|
return YamlLoader()
|
|
86
133
|
|
|
134
|
+
if ext == "yaml.j2":
|
|
135
|
+
from .loaders.yaml import YamlJ2Loader
|
|
136
|
+
return YamlJ2Loader()
|
|
137
|
+
|
|
138
|
+
if ext == "yaml.liq":
|
|
139
|
+
from .loaders.yaml import YamlLiqLoader
|
|
140
|
+
return YamlLiqLoader()
|
|
141
|
+
|
|
87
142
|
if ext == "yamls":
|
|
88
143
|
from .loaders.yaml import YamlsLoader
|
|
89
144
|
return YamlsLoader()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|