python-simpleconf 0.6.0__tar.gz → 0.6.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.
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/PKG-INFO +10 -10
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/pyproject.toml +9 -9
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/__init__.py +1 -1
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/caster.py +7 -4
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/config.py +72 -14
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/exceptions.py +0 -1
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/__init__.py +4 -2
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/env.py +7 -1
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/ini.py +21 -8
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/json.py +4 -0
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/osenv.py +2 -2
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/toml.py +5 -1
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/yaml.py +4 -0
- python_simpleconf-0.6.2/simpleconf/py.typed +0 -0
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/utils.py +13 -6
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/LICENSE +0 -0
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/README.md +0 -0
- {python_simpleconf-0.6.0 → python_simpleconf-0.6.2}/simpleconf/loaders/dict.py +0 -0
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: python-simpleconf
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Simple configuration management with python.
|
|
5
|
-
Home-page: https://github.com/pwwang/simpleconf
|
|
6
5
|
License: MIT
|
|
7
6
|
Author: pwwang
|
|
8
7
|
Author-email: pwwang@pwwang.com
|
|
9
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.9,<4.0
|
|
10
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
11
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
16
|
Provides-Extra: all
|
|
18
17
|
Provides-Extra: env
|
|
19
18
|
Provides-Extra: ini
|
|
20
19
|
Provides-Extra: toml
|
|
21
20
|
Provides-Extra: yaml
|
|
22
|
-
Requires-Dist: diot (>=0.
|
|
21
|
+
Requires-Dist: diot (>=0.3.1,<0.4.0)
|
|
23
22
|
Requires-Dist: iniconfig (>=2.0,<3.0) ; extra == "ini" or extra == "all"
|
|
24
|
-
Requires-Dist: python-dotenv (>=0.
|
|
23
|
+
Requires-Dist: python-dotenv (>=1.0,<2.0) ; extra == "env" or extra == "all"
|
|
25
24
|
Requires-Dist: pyyaml (>=6,<7) ; extra == "yaml" or extra == "all"
|
|
26
|
-
Requires-Dist: rtoml (>=0.
|
|
27
|
-
Requires-Dist: tomli (>=2.0,<3.0) ; (sys_platform != "linux"
|
|
25
|
+
Requires-Dist: rtoml (>=0.12,<0.13) ; (sys_platform == "linux") and (extra == "toml" or extra == "all")
|
|
26
|
+
Requires-Dist: tomli (>=2.0,<3.0) ; (sys_platform != "linux") and (extra == "toml" or extra == "all")
|
|
27
|
+
Project-URL: Homepage, https://github.com/pwwang/simpleconf
|
|
28
28
|
Project-URL: Repository, https://github.com/pwwang/simpleconf
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "python-simpleconf"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.2"
|
|
8
8
|
description = "Simple configuration management with python."
|
|
9
9
|
authors = [ "pwwang <pwwang@pwwang.com>",]
|
|
10
10
|
license = "MIT"
|
|
@@ -16,13 +16,13 @@ packages = [
|
|
|
16
16
|
]
|
|
17
17
|
|
|
18
18
|
[tool.poetry.dependencies]
|
|
19
|
-
python = "^3.
|
|
20
|
-
diot = "^0.
|
|
21
|
-
python-dotenv = { version="^0
|
|
19
|
+
python = "^3.9"
|
|
20
|
+
diot = "^0.3.1"
|
|
21
|
+
python-dotenv = { version="^1.0", optional = true}
|
|
22
22
|
pyyaml = { version="^6", optional = true}
|
|
23
23
|
# Use rtoml only when the wheel is available (linux)
|
|
24
|
-
rtoml = {version = "^0.
|
|
25
|
-
tomli = {version = "^2.0", optional = true,
|
|
24
|
+
rtoml = {version = "^0.12", optional = true, platform = "linux"}
|
|
25
|
+
tomli = {version = "^2.0", optional = true, markers = 'sys_platform != "linux"'}
|
|
26
26
|
iniconfig = {version = "^2.0", optional = true}
|
|
27
27
|
|
|
28
28
|
[tool.poetry.extras]
|
|
@@ -33,8 +33,8 @@ toml = [ "rtoml", "tomli"]
|
|
|
33
33
|
all = [ "iniconfig", "python-dotenv", "pyyaml", "rtoml", "tomli"]
|
|
34
34
|
|
|
35
35
|
[tool.poetry.dev-dependencies]
|
|
36
|
-
pytest = "^
|
|
37
|
-
pytest-cov = "^
|
|
36
|
+
pytest = "^8"
|
|
37
|
+
pytest-cov = "^6"
|
|
38
38
|
|
|
39
39
|
[tool.pytest.ini_options]
|
|
40
40
|
addopts = "-vv -p no:asyncio --cov=simpleconf --cov-report xml:cov.xml --cov-report term-missing"
|
|
@@ -45,6 +45,6 @@ console_output_style = "progress"
|
|
|
45
45
|
junit_family = "xunit1"
|
|
46
46
|
|
|
47
47
|
[tool.black]
|
|
48
|
-
line-length =
|
|
48
|
+
line-length = 88
|
|
49
49
|
target-version = ['py37', 'py38', 'py39', 'py310']
|
|
50
50
|
include = '\.pyi?$'
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
|
-
from typing import
|
|
4
|
+
from typing import Any, Callable, Sequence, TYPE_CHECKING
|
|
3
5
|
from ast import literal_eval
|
|
4
6
|
|
|
5
|
-
from simpleconf.utils import require_package
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from diot import Diot
|
|
@@ -47,6 +48,8 @@ def _cast_bool(value: str) -> bool:
|
|
|
47
48
|
|
|
48
49
|
def _cast_toml(value: str) -> Any:
|
|
49
50
|
"""Cast toml string"""
|
|
51
|
+
from .utils import require_package
|
|
52
|
+
|
|
50
53
|
toml = require_package("rtoml", "tomllib", "tomli")
|
|
51
54
|
return toml.loads(value)
|
|
52
55
|
|
|
@@ -74,11 +77,11 @@ def cast_value(value: Any, casters: Sequence[Callable]) -> Any:
|
|
|
74
77
|
return value
|
|
75
78
|
|
|
76
79
|
|
|
77
|
-
def cast(conf:
|
|
80
|
+
def cast(conf: Diot, casters: Sequence[Callable]) -> Diot:
|
|
78
81
|
"""Cast the configuration"""
|
|
79
82
|
for key, value in conf.items():
|
|
80
83
|
if isinstance(value, dict):
|
|
81
|
-
conf[key] = cast(value, casters)
|
|
84
|
+
conf[key] = cast(value, casters) # type: ignore[arg-type]
|
|
82
85
|
else:
|
|
83
86
|
conf[key] = cast_value(value, casters)
|
|
84
87
|
return conf
|
|
@@ -1,40 +1,60 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from contextlib import contextmanager
|
|
2
|
-
from typing import Any, List
|
|
4
|
+
from typing import Any, List, Generator, Union, Sequence
|
|
3
5
|
|
|
4
6
|
from diot import Diot
|
|
5
7
|
|
|
6
8
|
from .utils import config_to_ext, get_loader, POOL_KEY, META_KEY
|
|
9
|
+
from .loaders import Loader
|
|
10
|
+
|
|
11
|
+
LoaderType = Union[str, Loader, None]
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
class Config:
|
|
10
15
|
"""The configuration class"""
|
|
11
16
|
|
|
12
17
|
@staticmethod
|
|
13
|
-
def load(
|
|
18
|
+
def load(
|
|
19
|
+
*configs: Any,
|
|
20
|
+
loader: LoaderType | Sequence[LoaderType] = None,
|
|
21
|
+
ignore_nonexist: bool = False,
|
|
22
|
+
) -> Diot:
|
|
14
23
|
"""Load the configuration from the files, or other configurations
|
|
15
24
|
|
|
16
25
|
Args:
|
|
17
26
|
*configs: The configuration files or other configurations to load
|
|
18
27
|
Latter ones will override the former ones for items with the
|
|
19
28
|
same keys recursively.
|
|
29
|
+
loader: The loader to use. If a list is given, it must have the
|
|
30
|
+
same length as configs.
|
|
20
31
|
ignore_nonexist: Whether to ignore non-existent files
|
|
21
32
|
Otherwise, will raise errors
|
|
22
33
|
|
|
23
34
|
Returns:
|
|
24
35
|
A Diot object with the loaded configurations
|
|
25
36
|
"""
|
|
37
|
+
if not isinstance(loader, Sequence) or isinstance(loader, str):
|
|
38
|
+
loader = [loader] * len(configs)
|
|
39
|
+
|
|
40
|
+
if len(loader) != len(configs):
|
|
41
|
+
raise ValueError(
|
|
42
|
+
f"Length of loader ({len(loader)}) does not match "
|
|
43
|
+
f"length of configs ({len(configs)})"
|
|
44
|
+
)
|
|
45
|
+
|
|
26
46
|
out = Diot()
|
|
27
|
-
for conf in configs:
|
|
28
|
-
|
|
29
|
-
loader = get_loader(ext)
|
|
30
|
-
loaded = loader.load(conf, ignore_nonexist)
|
|
47
|
+
for i, conf in enumerate(configs):
|
|
48
|
+
loaded = Config.load_one(conf, loader[i], ignore_nonexist)
|
|
31
49
|
out.update_recursively(loaded)
|
|
32
50
|
|
|
33
51
|
return out
|
|
34
52
|
|
|
35
53
|
@staticmethod
|
|
36
54
|
def load_one(
|
|
37
|
-
config,
|
|
55
|
+
config,
|
|
56
|
+
loader: str | Loader | None = None,
|
|
57
|
+
ignore_nonexist: bool = False,
|
|
38
58
|
) -> Diot:
|
|
39
59
|
"""Load the configuration from the file
|
|
40
60
|
|
|
@@ -48,6 +68,9 @@ class Config:
|
|
|
48
68
|
A Diot object with the loaded configuration
|
|
49
69
|
"""
|
|
50
70
|
if loader is None:
|
|
71
|
+
if hasattr(config, "read"):
|
|
72
|
+
raise ValueError("'loader' must be specified for stream")
|
|
73
|
+
|
|
51
74
|
ext = config_to_ext(config)
|
|
52
75
|
loader = get_loader(ext)
|
|
53
76
|
else:
|
|
@@ -60,26 +83,50 @@ class ProfileConfig:
|
|
|
60
83
|
"""The configuration class with profile support"""
|
|
61
84
|
|
|
62
85
|
@staticmethod
|
|
63
|
-
def load(
|
|
86
|
+
def load(
|
|
87
|
+
*configs: Any,
|
|
88
|
+
loader: LoaderType | Sequence[LoaderType] = None,
|
|
89
|
+
ignore_nonexist: bool = False,
|
|
90
|
+
) -> Diot:
|
|
64
91
|
"""Load the configuration from the files, or other configurations
|
|
65
92
|
|
|
66
93
|
Args:
|
|
67
94
|
*configs: The configuration files or other configurations to load
|
|
68
95
|
Latter ones will override the former ones for items with the
|
|
69
96
|
same profile and keys recursively.
|
|
97
|
+
loader: The loader to use. If a list is given, it must have the
|
|
98
|
+
same length as configs.
|
|
70
99
|
ignore_nonexist: Whether to ignore non-existent files
|
|
71
100
|
Otherwise, will raise errors
|
|
72
101
|
"""
|
|
102
|
+
if not isinstance(loader, Sequence) or isinstance(loader, str):
|
|
103
|
+
loader = [loader] * len(configs)
|
|
104
|
+
|
|
105
|
+
if len(loader) != len(configs):
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"Length of loader ({len(loader)}) does not match "
|
|
108
|
+
f"length of configs ({len(configs)})"
|
|
109
|
+
)
|
|
110
|
+
|
|
73
111
|
out = Diot({POOL_KEY: Diot()})
|
|
74
112
|
pool = out[POOL_KEY]
|
|
75
113
|
out[META_KEY] = {
|
|
76
114
|
"current_profile": None,
|
|
77
115
|
"base_profile": None,
|
|
78
116
|
}
|
|
79
|
-
for conf in configs:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
117
|
+
for i, conf in enumerate(configs):
|
|
118
|
+
lder = loader[i]
|
|
119
|
+
|
|
120
|
+
if lder is None and hasattr(conf, "read"):
|
|
121
|
+
raise ValueError("'loader' must be specified for stream")
|
|
122
|
+
|
|
123
|
+
if lder is None:
|
|
124
|
+
ext = config_to_ext(conf)
|
|
125
|
+
lder = get_loader(ext)
|
|
126
|
+
else:
|
|
127
|
+
lder = get_loader(lder)
|
|
128
|
+
|
|
129
|
+
loaded = lder.load_with_profiles(conf, ignore_nonexist)
|
|
83
130
|
for profile, value in loaded.items():
|
|
84
131
|
profile = profile.lower()
|
|
85
132
|
pool.setdefault(profile, Diot())
|
|
@@ -90,7 +137,9 @@ class ProfileConfig:
|
|
|
90
137
|
|
|
91
138
|
@staticmethod
|
|
92
139
|
def load_one(
|
|
93
|
-
conf: Any,
|
|
140
|
+
conf: Any,
|
|
141
|
+
loader: str | Loader | None = None,
|
|
142
|
+
ignore_nonexist: bool = False,
|
|
94
143
|
) -> Diot:
|
|
95
144
|
"""Load the configuration from the file
|
|
96
145
|
|
|
@@ -112,6 +161,9 @@ class ProfileConfig:
|
|
|
112
161
|
}
|
|
113
162
|
|
|
114
163
|
if loader is None:
|
|
164
|
+
if hasattr(conf, "read"):
|
|
165
|
+
raise ValueError("'loader' must be specified for stream")
|
|
166
|
+
|
|
115
167
|
ext = config_to_ext(conf)
|
|
116
168
|
loader = get_loader(ext)
|
|
117
169
|
else:
|
|
@@ -167,6 +219,8 @@ class ProfileConfig:
|
|
|
167
219
|
conf[META_KEY]["current_profile"] = profile
|
|
168
220
|
conf[META_KEY]["base_profile"] = base
|
|
169
221
|
|
|
222
|
+
return conf
|
|
223
|
+
|
|
170
224
|
@staticmethod
|
|
171
225
|
def current_profile(conf: Diot) -> str:
|
|
172
226
|
"""Get the current profile"""
|
|
@@ -228,7 +282,11 @@ class ProfileConfig:
|
|
|
228
282
|
|
|
229
283
|
@staticmethod
|
|
230
284
|
@contextmanager
|
|
231
|
-
def with_profile(
|
|
285
|
+
def with_profile(
|
|
286
|
+
conf: Diot,
|
|
287
|
+
profile: str,
|
|
288
|
+
base: str = "default",
|
|
289
|
+
) -> Generator[Diot, None, None]:
|
|
232
290
|
"""A context manager to use the given profile
|
|
233
291
|
|
|
234
292
|
Args:
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from abc import ABC, abstractmethod
|
|
2
4
|
from os import PathLike
|
|
3
5
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, List
|
|
5
7
|
|
|
6
8
|
from ..caster import cast
|
|
7
9
|
|
|
@@ -11,7 +13,7 @@ if TYPE_CHECKING:
|
|
|
11
13
|
|
|
12
14
|
class Loader(ABC):
|
|
13
15
|
|
|
14
|
-
CASTERS = None
|
|
16
|
+
CASTERS: List[Callable[[str, bool], Any]] | None = None
|
|
15
17
|
|
|
16
18
|
@abstractmethod
|
|
17
19
|
def loading(self, conf: Any, ignore_nonexist: bool) -> "Diot":
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import warnings
|
|
2
|
+
import io
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Any
|
|
4
5
|
from simpleconf.utils import require_package
|
|
@@ -36,11 +37,16 @@ class EnvLoader(Loader):
|
|
|
36
37
|
|
|
37
38
|
def loading(self, conf: Any, ignore_nonexist: bool = False) -> Diot:
|
|
38
39
|
"""Load the configuration from a .env file"""
|
|
40
|
+
if hasattr(conf, "read"):
|
|
41
|
+
content = conf.read()
|
|
42
|
+
return Diot(dotenv.dotenv_values(stream=io.StringIO(content)))
|
|
43
|
+
|
|
39
44
|
if not self._exists(conf, ignore_nonexist):
|
|
40
45
|
return Diot()
|
|
46
|
+
|
|
41
47
|
return Diot(dotenv.main.DotEnv(conf).dict())
|
|
42
48
|
|
|
43
|
-
def load_with_profiles(
|
|
49
|
+
def load_with_profiles( # type: ignore[override]
|
|
44
50
|
self,
|
|
45
51
|
conf: Any,
|
|
46
52
|
ignore_nonexist: bool = False,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import warnings
|
|
2
4
|
from typing import Any
|
|
3
5
|
from pathlib import Path
|
|
@@ -34,37 +36,48 @@ class IniLoader(Loader):
|
|
|
34
36
|
toml_caster,
|
|
35
37
|
]
|
|
36
38
|
|
|
37
|
-
def loading(self, conf: Any, ignore_nonexist: bool) ->
|
|
39
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
38
40
|
"""Load the configuration from an ini-like file"""
|
|
41
|
+
if hasattr(conf, "read"):
|
|
42
|
+
content = conf.read()
|
|
43
|
+
return iniconfig.IniConfig("<config>", content).sections
|
|
44
|
+
|
|
39
45
|
if not self._exists(conf, ignore_nonexist):
|
|
40
46
|
return Diot(default={})
|
|
47
|
+
|
|
41
48
|
return iniconfig.IniConfig(conf).sections
|
|
42
49
|
|
|
43
|
-
def load(self, conf: Any, ignore_nonexist: bool = False) ->
|
|
50
|
+
def load(self, conf: Any, ignore_nonexist: bool = False) -> Diot:
|
|
44
51
|
"""Load and cast the configuration from an ini-like file"""
|
|
45
52
|
sections = self.loading(conf, ignore_nonexist)
|
|
46
53
|
keys = list(sections)
|
|
54
|
+
|
|
55
|
+
if hasattr(conf, "read"):
|
|
56
|
+
pathname = "<config>"
|
|
57
|
+
else:
|
|
58
|
+
pathname = Path(conf).name
|
|
59
|
+
|
|
47
60
|
# only load the default section
|
|
48
61
|
if len(keys) > 1:
|
|
49
62
|
warnings.warn(
|
|
50
|
-
f"{
|
|
51
|
-
"only the default section will be loaded."
|
|
63
|
+
f"{pathname}: More than one section found, "
|
|
64
|
+
"only the default section will be loaded. "
|
|
65
|
+
"Use ProfileConfig.load() if you want to sections as profiles."
|
|
52
66
|
)
|
|
53
67
|
|
|
54
68
|
if len(keys) == 0 or keys[0].lower() != "default":
|
|
55
69
|
raise ValueError(
|
|
56
|
-
f"{
|
|
70
|
+
f"{pathname}: Only the default section can be loaded."
|
|
57
71
|
)
|
|
58
72
|
|
|
59
73
|
return cast(Diot(sections[keys[0]]), self.__class__.CASTERS)
|
|
60
74
|
|
|
61
|
-
def load_with_profiles(
|
|
75
|
+
def load_with_profiles( # type: ignore[override]
|
|
62
76
|
self,
|
|
63
77
|
conf: Any,
|
|
64
78
|
ignore_nonexist: bool = False,
|
|
65
79
|
) -> Diot:
|
|
66
|
-
"""Load and cast the configuration from an ini-like file with profiles
|
|
67
|
-
"""
|
|
80
|
+
"""Load and cast the configuration from an ini-like file with profiles"""
|
|
68
81
|
sections = self.loading(conf, ignore_nonexist)
|
|
69
82
|
out = Diot()
|
|
70
83
|
for k, v in sections.items():
|
|
@@ -11,6 +11,10 @@ class JsonLoader(Loader):
|
|
|
11
11
|
|
|
12
12
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
13
13
|
"""Load the configuration from a json file"""
|
|
14
|
+
if hasattr(conf, "read"):
|
|
15
|
+
content = conf.read()
|
|
16
|
+
return Diot(json.loads(content))
|
|
17
|
+
|
|
14
18
|
if not self._exists(conf, ignore_nonexist):
|
|
15
19
|
return Diot()
|
|
16
20
|
with open(conf) as f:
|
|
@@ -39,10 +39,10 @@ class OsenvLoader(Loader):
|
|
|
39
39
|
out = Diot()
|
|
40
40
|
for k, v in environ.items():
|
|
41
41
|
if k.startswith(prefix):
|
|
42
|
-
out[k[len_prefix
|
|
42
|
+
out[k[len_prefix:]] = v
|
|
43
43
|
return out
|
|
44
44
|
|
|
45
|
-
def load_with_profiles(
|
|
45
|
+
def load_with_profiles( # type: ignore[override]
|
|
46
46
|
self,
|
|
47
47
|
conf: Any,
|
|
48
48
|
ignore_nonexist: bool = False,
|
|
@@ -21,6 +21,10 @@ class TomlLoader(Loader):
|
|
|
21
21
|
|
|
22
22
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
23
23
|
"""Load the configuration from a toml file"""
|
|
24
|
+
if hasattr(conf, "read"):
|
|
25
|
+
content = conf.read()
|
|
26
|
+
return Diot(toml.loads(content))
|
|
27
|
+
|
|
24
28
|
if not self._exists(conf, ignore_nonexist):
|
|
25
29
|
return Diot()
|
|
26
30
|
|
|
@@ -28,5 +32,5 @@ class TomlLoader(Loader):
|
|
|
28
32
|
with open(conf, "rb") as f:
|
|
29
33
|
return Diot(toml.load(f))
|
|
30
34
|
|
|
31
|
-
with open(conf, "r") as f:
|
|
35
|
+
with open(conf, "r") as f: # rtoml
|
|
32
36
|
return Diot(toml.load(f))
|
|
@@ -12,6 +12,10 @@ class YamlLoader(Loader):
|
|
|
12
12
|
|
|
13
13
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
14
14
|
"""Load the configuration from a yaml file"""
|
|
15
|
+
if hasattr(conf, "read"):
|
|
16
|
+
content = conf.read()
|
|
17
|
+
return Diot(yaml.load(content, Loader=yaml.FullLoader))
|
|
18
|
+
|
|
15
19
|
if not self._exists(conf, ignore_nonexist):
|
|
16
20
|
return Diot()
|
|
17
21
|
|
|
File without changes
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
1
|
from __future__ import annotations
|
|
3
2
|
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from importlib import import_module
|
|
6
5
|
from types import ModuleType
|
|
7
|
-
from typing import
|
|
6
|
+
from typing import Any
|
|
8
7
|
|
|
9
8
|
from .exceptions import FormatNotSupported
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from .loaders import Loader
|
|
9
|
+
from .loaders import Loader
|
|
13
10
|
|
|
14
11
|
POOL_KEY = "_SIMPLECONF_POOL"
|
|
15
12
|
META_KEY = "_SIMPLECONF_META"
|
|
@@ -34,28 +31,38 @@ def config_to_ext(conf: Any) -> str:
|
|
|
34
31
|
return out
|
|
35
32
|
|
|
36
33
|
|
|
37
|
-
def get_loader(ext: str) -> Loader:
|
|
34
|
+
def get_loader(ext: str | Loader) -> Loader:
|
|
38
35
|
"""Get the loader for the extension"""
|
|
36
|
+
if isinstance(ext, Loader):
|
|
37
|
+
return ext
|
|
38
|
+
|
|
39
39
|
if ext == "dict":
|
|
40
40
|
from .loaders.dict import DictLoader
|
|
41
|
+
|
|
41
42
|
return DictLoader()
|
|
42
43
|
if ext == "env":
|
|
43
44
|
from .loaders.env import EnvLoader
|
|
45
|
+
|
|
44
46
|
return EnvLoader()
|
|
45
47
|
if ext == "ini":
|
|
46
48
|
from .loaders.ini import IniLoader
|
|
49
|
+
|
|
47
50
|
return IniLoader()
|
|
48
51
|
if ext == "json":
|
|
49
52
|
from .loaders.json import JsonLoader
|
|
53
|
+
|
|
50
54
|
return JsonLoader()
|
|
51
55
|
if ext == "osenv":
|
|
52
56
|
from .loaders.osenv import OsenvLoader
|
|
57
|
+
|
|
53
58
|
return OsenvLoader()
|
|
54
59
|
if ext == "toml":
|
|
55
60
|
from .loaders.toml import TomlLoader
|
|
61
|
+
|
|
56
62
|
return TomlLoader()
|
|
57
63
|
if ext == "yaml":
|
|
58
64
|
from .loaders.yaml import YamlLoader
|
|
65
|
+
|
|
59
66
|
return YamlLoader()
|
|
60
67
|
|
|
61
68
|
raise FormatNotSupported(f"{ext} is not supported.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|