python-simpleconf 0.6.1__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.1 → python_simpleconf-0.6.2}/PKG-INFO +1 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/pyproject.toml +1 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/__init__.py +1 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/config.py +56 -13
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/env.py +6 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/ini.py +15 -3
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/json.py +4 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/toml.py +4 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/yaml.py +4 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/LICENSE +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/README.md +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/caster.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/exceptions.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/__init__.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/dict.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/loaders/osenv.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/py.typed +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.6.2}/simpleconf/utils.py +0 -0
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from contextlib import contextmanager
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Any, List, Generator, Union, Sequence
|
|
5
5
|
|
|
6
6
|
from diot import Diot
|
|
7
7
|
|
|
8
8
|
from .utils import config_to_ext, get_loader, POOL_KEY, META_KEY
|
|
9
|
+
from .loaders import Loader
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
from .loaders import Loader
|
|
11
|
+
LoaderType = Union[str, Loader, None]
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Config:
|
|
15
15
|
"""The configuration class"""
|
|
16
16
|
|
|
17
17
|
@staticmethod
|
|
18
|
-
def load(
|
|
18
|
+
def load(
|
|
19
|
+
*configs: Any,
|
|
20
|
+
loader: LoaderType | Sequence[LoaderType] = None,
|
|
21
|
+
ignore_nonexist: bool = False,
|
|
22
|
+
) -> Diot:
|
|
19
23
|
"""Load the configuration from the files, or other configurations
|
|
20
24
|
|
|
21
25
|
Args:
|
|
22
26
|
*configs: The configuration files or other configurations to load
|
|
23
27
|
Latter ones will override the former ones for items with the
|
|
24
28
|
same keys recursively.
|
|
29
|
+
loader: The loader to use. If a list is given, it must have the
|
|
30
|
+
same length as configs.
|
|
25
31
|
ignore_nonexist: Whether to ignore non-existent files
|
|
26
32
|
Otherwise, will raise errors
|
|
27
33
|
|
|
28
34
|
Returns:
|
|
29
35
|
A Diot object with the loaded configurations
|
|
30
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
|
+
|
|
31
46
|
out = Diot()
|
|
32
|
-
for conf in configs:
|
|
33
|
-
|
|
34
|
-
loader = get_loader(ext)
|
|
35
|
-
loaded = loader.load(conf, ignore_nonexist)
|
|
47
|
+
for i, conf in enumerate(configs):
|
|
48
|
+
loaded = Config.load_one(conf, loader[i], ignore_nonexist)
|
|
36
49
|
out.update_recursively(loaded)
|
|
37
50
|
|
|
38
51
|
return out
|
|
@@ -55,6 +68,9 @@ class Config:
|
|
|
55
68
|
A Diot object with the loaded configuration
|
|
56
69
|
"""
|
|
57
70
|
if loader is None:
|
|
71
|
+
if hasattr(config, "read"):
|
|
72
|
+
raise ValueError("'loader' must be specified for stream")
|
|
73
|
+
|
|
58
74
|
ext = config_to_ext(config)
|
|
59
75
|
loader = get_loader(ext)
|
|
60
76
|
else:
|
|
@@ -67,26 +83,50 @@ class ProfileConfig:
|
|
|
67
83
|
"""The configuration class with profile support"""
|
|
68
84
|
|
|
69
85
|
@staticmethod
|
|
70
|
-
def load(
|
|
86
|
+
def load(
|
|
87
|
+
*configs: Any,
|
|
88
|
+
loader: LoaderType | Sequence[LoaderType] = None,
|
|
89
|
+
ignore_nonexist: bool = False,
|
|
90
|
+
) -> Diot:
|
|
71
91
|
"""Load the configuration from the files, or other configurations
|
|
72
92
|
|
|
73
93
|
Args:
|
|
74
94
|
*configs: The configuration files or other configurations to load
|
|
75
95
|
Latter ones will override the former ones for items with the
|
|
76
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.
|
|
77
99
|
ignore_nonexist: Whether to ignore non-existent files
|
|
78
100
|
Otherwise, will raise errors
|
|
79
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
|
+
|
|
80
111
|
out = Diot({POOL_KEY: Diot()})
|
|
81
112
|
pool = out[POOL_KEY]
|
|
82
113
|
out[META_KEY] = {
|
|
83
114
|
"current_profile": None,
|
|
84
115
|
"base_profile": None,
|
|
85
116
|
}
|
|
86
|
-
for conf in configs:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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)
|
|
90
130
|
for profile, value in loaded.items():
|
|
91
131
|
profile = profile.lower()
|
|
92
132
|
pool.setdefault(profile, Diot())
|
|
@@ -121,6 +161,9 @@ class ProfileConfig:
|
|
|
121
161
|
}
|
|
122
162
|
|
|
123
163
|
if loader is None:
|
|
164
|
+
if hasattr(conf, "read"):
|
|
165
|
+
raise ValueError("'loader' must be specified for stream")
|
|
166
|
+
|
|
124
167
|
ext = config_to_ext(conf)
|
|
125
168
|
loader = get_loader(ext)
|
|
126
169
|
else:
|
|
@@ -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,8 +37,13 @@ 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
49
|
def load_with_profiles( # type: ignore[override]
|
|
@@ -38,24 +38,36 @@ class IniLoader(Loader):
|
|
|
38
38
|
|
|
39
39
|
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
40
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
|
+
|
|
41
45
|
if not self._exists(conf, ignore_nonexist):
|
|
42
46
|
return Diot(default={})
|
|
47
|
+
|
|
43
48
|
return iniconfig.IniConfig(conf).sections
|
|
44
49
|
|
|
45
50
|
def load(self, conf: Any, ignore_nonexist: bool = False) -> Diot:
|
|
46
51
|
"""Load and cast the configuration from an ini-like file"""
|
|
47
52
|
sections = self.loading(conf, ignore_nonexist)
|
|
48
53
|
keys = list(sections)
|
|
54
|
+
|
|
55
|
+
if hasattr(conf, "read"):
|
|
56
|
+
pathname = "<config>"
|
|
57
|
+
else:
|
|
58
|
+
pathname = Path(conf).name
|
|
59
|
+
|
|
49
60
|
# only load the default section
|
|
50
61
|
if len(keys) > 1:
|
|
51
62
|
warnings.warn(
|
|
52
|
-
f"{
|
|
53
|
-
"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."
|
|
54
66
|
)
|
|
55
67
|
|
|
56
68
|
if len(keys) == 0 or keys[0].lower() != "default":
|
|
57
69
|
raise ValueError(
|
|
58
|
-
f"{
|
|
70
|
+
f"{pathname}: Only the default section can be loaded."
|
|
59
71
|
)
|
|
60
72
|
|
|
61
73
|
return cast(Diot(sections[keys[0]]), self.__class__.CASTERS)
|
|
@@ -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:
|
|
@@ -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
|
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|