python-simpleconf 0.6.1__tar.gz → 0.7.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.6.1 → python_simpleconf-0.7.0}/PKG-INFO +3 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/README.md +2 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/pyproject.toml +1 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/__init__.py +1 -1
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/caster.py +3 -4
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/config.py +56 -13
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/loaders/__init__.py +7 -8
- python_simpleconf-0.7.0/simpleconf/loaders/dict.py +19 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/loaders/env.py +19 -5
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/loaders/ini.py +27 -7
- python_simpleconf-0.7.0/simpleconf/loaders/json.py +28 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/loaders/osenv.py +3 -3
- python_simpleconf-0.7.0/simpleconf/loaders/toml.py +43 -0
- python_simpleconf-0.7.0/simpleconf/loaders/yaml.py +30 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/utils.py +30 -7
- python_simpleconf-0.6.1/simpleconf/loaders/dict.py +0 -12
- python_simpleconf-0.6.1/simpleconf/loaders/json.py +0 -17
- python_simpleconf-0.6.1/simpleconf/loaders/toml.py +0 -32
- python_simpleconf-0.6.1/simpleconf/loaders/yaml.py +0 -19
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/LICENSE +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/exceptions.py +0 -0
- {python_simpleconf-0.6.1 → python_simpleconf-0.7.0}/simpleconf/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python-simpleconf
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Simple configuration management with python.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: pwwang
|
|
@@ -99,6 +99,8 @@ conf = Config.load({'a': 1, 'b': {'c': 2}})
|
|
|
99
99
|
- `XXX.osenv`: System environment variables with prefix `XXX_` (case-sensitive) is used.
|
|
100
100
|
- `XXX_A=1` will be loaded as `conf.A = 1`.
|
|
101
101
|
- python dictionary.
|
|
102
|
+
- Strings format of the above formats are also supported.
|
|
103
|
+
- `"{'a': 1}"` will be loaded as `conf.a = 1`.
|
|
102
104
|
|
|
103
105
|
### Profile support
|
|
104
106
|
|
|
@@ -69,6 +69,8 @@ conf = Config.load({'a': 1, 'b': {'c': 2}})
|
|
|
69
69
|
- `XXX.osenv`: System environment variables with prefix `XXX_` (case-sensitive) is used.
|
|
70
70
|
- `XXX_A=1` will be loaded as `conf.A = 1`.
|
|
71
71
|
- python dictionary.
|
|
72
|
+
- Strings format of the above formats are also supported.
|
|
73
|
+
- `"{'a': 1}"` will be loaded as `conf.a = 1`.
|
|
72
74
|
|
|
73
75
|
### Profile support
|
|
74
76
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from typing import Any, Callable, Sequence,
|
|
4
|
+
from typing import Any, Callable, Dict, Sequence, TypeVar
|
|
5
5
|
from ast import literal_eval
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
from diot import Diot
|
|
8
|
+
T = TypeVar("T", bound=Dict[str, Any])
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def type_caster(prefix: str, cast_fun: Callable) -> Any:
|
|
@@ -77,7 +76,7 @@ def cast_value(value: Any, casters: Sequence[Callable]) -> Any:
|
|
|
77
76
|
return value
|
|
78
77
|
|
|
79
78
|
|
|
80
|
-
def cast(conf:
|
|
79
|
+
def cast(conf: T, casters: Sequence[Callable]) -> T:
|
|
81
80
|
"""Cast the configuration"""
|
|
82
81
|
for key, value in conf.items():
|
|
83
82
|
if isinstance(value, dict):
|
|
@@ -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:
|
|
@@ -3,20 +3,18 @@ from __future__ import annotations
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
from os import PathLike
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Any, Callable, List, Dict
|
|
7
7
|
|
|
8
|
+
from diot import Diot
|
|
8
9
|
from ..caster import cast
|
|
9
10
|
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from diot import Diot
|
|
12
|
-
|
|
13
11
|
|
|
14
12
|
class Loader(ABC):
|
|
15
13
|
|
|
16
14
|
CASTERS: List[Callable[[str, bool], Any]] | None = None
|
|
17
15
|
|
|
18
16
|
@abstractmethod
|
|
19
|
-
def loading(self, conf: Any, ignore_nonexist: bool) ->
|
|
17
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
20
18
|
"""Load the configuration from the path or configurations"""
|
|
21
19
|
|
|
22
20
|
def _exists(self, conf: PathLike, ignore_exist: bool) -> bool:
|
|
@@ -26,7 +24,7 @@ class Loader(ABC):
|
|
|
26
24
|
raise FileNotFoundError(f"{conf} does not exist")
|
|
27
25
|
return path.exists()
|
|
28
26
|
|
|
29
|
-
def load(self, conf: Any, ignore_nonexist: bool = False) ->
|
|
27
|
+
def load(self, conf: Any, ignore_nonexist: bool = False) -> Diot:
|
|
30
28
|
"""Load the configuration from the path or configurations and cast
|
|
31
29
|
values
|
|
32
30
|
|
|
@@ -38,7 +36,8 @@ class Loader(ABC):
|
|
|
38
36
|
"""
|
|
39
37
|
loaded = self.loading(conf, ignore_nonexist)
|
|
40
38
|
if self.__class__.CASTERS:
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
loaded = cast(loaded, self.__class__.CASTERS)
|
|
40
|
+
|
|
41
|
+
return Diot(loaded)
|
|
43
42
|
|
|
44
43
|
load_with_profiles = load
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from . import Loader
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DictLoader(Loader):
|
|
7
|
+
"""Dict loader"""
|
|
8
|
+
|
|
9
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
10
|
+
"""Load the configuration from a dict"""
|
|
11
|
+
return conf
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DictsLoader(DictLoader):
|
|
15
|
+
"""Dict string loader"""
|
|
16
|
+
|
|
17
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
18
|
+
"""Load the configuration from a dict"""
|
|
19
|
+
return eval(conf)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import warnings
|
|
2
|
+
import io
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Any
|
|
4
|
-
from simpleconf.utils import require_package
|
|
4
|
+
from typing import Any, Dict
|
|
5
5
|
from diot import Diot
|
|
6
6
|
|
|
7
|
+
from ..utils import require_package
|
|
7
8
|
from ..caster import (
|
|
8
9
|
cast,
|
|
9
10
|
int_caster,
|
|
@@ -34,11 +35,16 @@ class EnvLoader(Loader):
|
|
|
34
35
|
toml_caster,
|
|
35
36
|
]
|
|
36
37
|
|
|
37
|
-
def loading(self, conf: Any, ignore_nonexist: bool = False) ->
|
|
38
|
+
def loading(self, conf: Any, ignore_nonexist: bool = False) -> Dict[str, Any]:
|
|
38
39
|
"""Load the configuration from a .env file"""
|
|
40
|
+
if hasattr(conf, "read"):
|
|
41
|
+
content = conf.read()
|
|
42
|
+
return dotenv.dotenv_values(stream=io.StringIO(content))
|
|
43
|
+
|
|
39
44
|
if not self._exists(conf, ignore_nonexist):
|
|
40
|
-
return
|
|
41
|
-
|
|
45
|
+
return {}
|
|
46
|
+
|
|
47
|
+
return dotenv.main.DotEnv(conf).dict()
|
|
42
48
|
|
|
43
49
|
def load_with_profiles( # type: ignore[override]
|
|
44
50
|
self,
|
|
@@ -59,3 +65,11 @@ class EnvLoader(Loader):
|
|
|
59
65
|
out.setdefault(profile, Diot())[key] = v
|
|
60
66
|
|
|
61
67
|
return cast(out, self.__class__.CASTERS)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class EnvsLoader(EnvLoader):
|
|
71
|
+
"""Env string loader"""
|
|
72
|
+
|
|
73
|
+
def loading(self, conf: Any, ignore_nonexist: bool = False) -> Dict[str, Any]:
|
|
74
|
+
"""Load the configuration from a .env file"""
|
|
75
|
+
return dotenv.dotenv_values(stream=io.StringIO(conf))
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any, Dict
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from simpleconf.utils import require_package
|
|
7
6
|
from diot import Diot
|
|
8
7
|
|
|
8
|
+
from ..utils import require_package
|
|
9
9
|
from ..caster import (
|
|
10
10
|
cast,
|
|
11
11
|
int_caster,
|
|
@@ -36,26 +36,38 @@ class IniLoader(Loader):
|
|
|
36
36
|
toml_caster,
|
|
37
37
|
]
|
|
38
38
|
|
|
39
|
-
def loading(self, conf: Any, ignore_nonexist: bool) ->
|
|
39
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
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
|
-
return
|
|
46
|
+
return {"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)
|
|
@@ -71,3 +83,11 @@ class IniLoader(Loader):
|
|
|
71
83
|
for k, v in sections.items():
|
|
72
84
|
out[k.lower()] = cast(v, self.__class__.CASTERS)
|
|
73
85
|
return out
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class InisLoader(IniLoader):
|
|
89
|
+
"""Ini-like string loader"""
|
|
90
|
+
|
|
91
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
92
|
+
"""Load the configuration from an ini-like file"""
|
|
93
|
+
return iniconfig.IniConfig("<config>", conf).sections
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from . import Loader
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class JsonLoader(Loader):
|
|
8
|
+
"""Json file loader"""
|
|
9
|
+
|
|
10
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
11
|
+
"""Load the configuration from a json file"""
|
|
12
|
+
if hasattr(conf, "read"):
|
|
13
|
+
content = conf.read()
|
|
14
|
+
return json.loads(content)
|
|
15
|
+
|
|
16
|
+
if not self._exists(conf, ignore_nonexist):
|
|
17
|
+
return {}
|
|
18
|
+
|
|
19
|
+
with open(conf) as f:
|
|
20
|
+
return json.load(f)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class JsonsLoader(JsonLoader):
|
|
24
|
+
"""Json string loader"""
|
|
25
|
+
|
|
26
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
27
|
+
"""Load the configuration from a json file"""
|
|
28
|
+
return json.loads(conf)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from os import environ
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any, Dict
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
5
|
from diot import Diot
|
|
@@ -32,11 +32,11 @@ class OsenvLoader(Loader):
|
|
|
32
32
|
toml_caster,
|
|
33
33
|
]
|
|
34
34
|
|
|
35
|
-
def loading(self, conf: Any, ignore_nonexist: bool = False) ->
|
|
35
|
+
def loading(self, conf: Any, ignore_nonexist: bool = False) -> Dict[str, Any]:
|
|
36
36
|
"""Load the configuration from environment variables"""
|
|
37
37
|
prefix = f"{conf[:-6]}_" if len(conf) > 6 else ""
|
|
38
38
|
len_prefix = len(prefix)
|
|
39
|
-
out =
|
|
39
|
+
out = {}
|
|
40
40
|
for k, v in environ.items():
|
|
41
41
|
if k.startswith(prefix):
|
|
42
42
|
out[k[len_prefix:]] = v
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from ..utils import require_package
|
|
4
|
+
from ..caster import (
|
|
5
|
+
none_caster,
|
|
6
|
+
null_caster,
|
|
7
|
+
)
|
|
8
|
+
from . import Loader
|
|
9
|
+
|
|
10
|
+
toml = require_package("rtoml", "tomllib", "tomli")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TomlLoader(Loader):
|
|
14
|
+
"""Toml file loader"""
|
|
15
|
+
|
|
16
|
+
CASTERS = [
|
|
17
|
+
none_caster,
|
|
18
|
+
null_caster,
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
22
|
+
"""Load the configuration from a toml file"""
|
|
23
|
+
if hasattr(conf, "read"):
|
|
24
|
+
content = conf.read()
|
|
25
|
+
return toml.loads(content)
|
|
26
|
+
|
|
27
|
+
if not self._exists(conf, ignore_nonexist):
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
if toml.__name__ in ("tomli", "tomllib"): # pragma: no cover
|
|
31
|
+
with open(conf, "rb") as f:
|
|
32
|
+
return toml.load(f)
|
|
33
|
+
|
|
34
|
+
with open(conf, "r") as f: # rtoml
|
|
35
|
+
return toml.load(f)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TomlsLoader(TomlLoader):
|
|
39
|
+
"""Toml string loader"""
|
|
40
|
+
|
|
41
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
42
|
+
"""Load the configuration from a toml file"""
|
|
43
|
+
return toml.loads(conf)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from . import Loader
|
|
4
|
+
from ..utils import require_package
|
|
5
|
+
|
|
6
|
+
yaml = require_package("yaml")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class YamlLoader(Loader):
|
|
10
|
+
"""Yaml file loader"""
|
|
11
|
+
|
|
12
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
13
|
+
"""Load the configuration from a yaml file"""
|
|
14
|
+
if hasattr(conf, "read"):
|
|
15
|
+
content = conf.read()
|
|
16
|
+
return yaml.load(content, Loader=yaml.FullLoader)
|
|
17
|
+
|
|
18
|
+
if not self._exists(conf, ignore_nonexist):
|
|
19
|
+
return {}
|
|
20
|
+
|
|
21
|
+
with open(conf) as f:
|
|
22
|
+
return yaml.load(f, Loader=yaml.FullLoader)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class YamlsLoader(YamlLoader):
|
|
26
|
+
"""Yaml string loader"""
|
|
27
|
+
|
|
28
|
+
def loading(self, conf: Any, ignore_nonexist: bool) -> Dict[str, Any]:
|
|
29
|
+
"""Load the configuration from a yaml file"""
|
|
30
|
+
return yaml.load(conf, Loader=yaml.FullLoader)
|
|
@@ -38,33 +38,56 @@ def get_loader(ext: str | Loader) -> Loader:
|
|
|
38
38
|
|
|
39
39
|
if ext == "dict":
|
|
40
40
|
from .loaders.dict import DictLoader
|
|
41
|
-
|
|
42
41
|
return DictLoader()
|
|
42
|
+
|
|
43
|
+
if ext == "dicts":
|
|
44
|
+
from .loaders.dict import DictsLoader
|
|
45
|
+
return DictsLoader()
|
|
46
|
+
|
|
43
47
|
if ext == "env":
|
|
44
48
|
from .loaders.env import EnvLoader
|
|
45
|
-
|
|
46
49
|
return EnvLoader()
|
|
50
|
+
|
|
51
|
+
if ext == "envs":
|
|
52
|
+
from .loaders.env import EnvsLoader
|
|
53
|
+
return EnvsLoader()
|
|
54
|
+
|
|
47
55
|
if ext == "ini":
|
|
48
56
|
from .loaders.ini import IniLoader
|
|
49
|
-
|
|
50
57
|
return IniLoader()
|
|
58
|
+
|
|
59
|
+
if ext == "inis":
|
|
60
|
+
from .loaders.ini import InisLoader
|
|
61
|
+
return InisLoader()
|
|
62
|
+
|
|
51
63
|
if ext == "json":
|
|
52
64
|
from .loaders.json import JsonLoader
|
|
53
|
-
|
|
54
65
|
return JsonLoader()
|
|
66
|
+
|
|
67
|
+
if ext == "jsons":
|
|
68
|
+
from .loaders.json import JsonsLoader
|
|
69
|
+
return JsonsLoader()
|
|
70
|
+
|
|
55
71
|
if ext == "osenv":
|
|
56
72
|
from .loaders.osenv import OsenvLoader
|
|
57
|
-
|
|
58
73
|
return OsenvLoader()
|
|
74
|
+
|
|
59
75
|
if ext == "toml":
|
|
60
76
|
from .loaders.toml import TomlLoader
|
|
61
|
-
|
|
62
77
|
return TomlLoader()
|
|
78
|
+
|
|
79
|
+
if ext == "tomls":
|
|
80
|
+
from .loaders.toml import TomlsLoader
|
|
81
|
+
return TomlsLoader()
|
|
82
|
+
|
|
63
83
|
if ext == "yaml":
|
|
64
84
|
from .loaders.yaml import YamlLoader
|
|
65
|
-
|
|
66
85
|
return YamlLoader()
|
|
67
86
|
|
|
87
|
+
if ext == "yamls":
|
|
88
|
+
from .loaders.yaml import YamlsLoader
|
|
89
|
+
return YamlsLoader()
|
|
90
|
+
|
|
68
91
|
raise FormatNotSupported(f"{ext} is not supported.")
|
|
69
92
|
|
|
70
93
|
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from diot import Diot
|
|
5
|
-
|
|
6
|
-
from . import Loader
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class JsonLoader(Loader):
|
|
10
|
-
"""Json file loader"""
|
|
11
|
-
|
|
12
|
-
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
13
|
-
"""Load the configuration from a json file"""
|
|
14
|
-
if not self._exists(conf, ignore_nonexist):
|
|
15
|
-
return Diot()
|
|
16
|
-
with open(conf) as f:
|
|
17
|
-
return Diot(json.load(f))
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
from simpleconf.utils import require_package
|
|
3
|
-
from diot import Diot
|
|
4
|
-
|
|
5
|
-
from ..caster import (
|
|
6
|
-
none_caster,
|
|
7
|
-
null_caster,
|
|
8
|
-
)
|
|
9
|
-
from . import Loader
|
|
10
|
-
|
|
11
|
-
toml = require_package("rtoml", "tomllib", "tomli")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TomlLoader(Loader):
|
|
15
|
-
"""Toml file loader"""
|
|
16
|
-
|
|
17
|
-
CASTERS = [
|
|
18
|
-
none_caster,
|
|
19
|
-
null_caster,
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
23
|
-
"""Load the configuration from a toml file"""
|
|
24
|
-
if not self._exists(conf, ignore_nonexist):
|
|
25
|
-
return Diot()
|
|
26
|
-
|
|
27
|
-
if toml.__name__ in ("tomli", "tomllib"): # pragma: no cover
|
|
28
|
-
with open(conf, "rb") as f:
|
|
29
|
-
return Diot(toml.load(f))
|
|
30
|
-
|
|
31
|
-
with open(conf, "r") as f: # rtoml
|
|
32
|
-
return Diot(toml.load(f))
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
from simpleconf.utils import require_package
|
|
3
|
-
from diot import Diot
|
|
4
|
-
|
|
5
|
-
from . import Loader
|
|
6
|
-
|
|
7
|
-
yaml = require_package("yaml")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class YamlLoader(Loader):
|
|
11
|
-
"""Yaml file loader"""
|
|
12
|
-
|
|
13
|
-
def loading(self, conf: Any, ignore_nonexist: bool) -> Diot:
|
|
14
|
-
"""Load the configuration from a yaml file"""
|
|
15
|
-
if not self._exists(conf, ignore_nonexist):
|
|
16
|
-
return Diot()
|
|
17
|
-
|
|
18
|
-
with open(conf) as f:
|
|
19
|
-
return Diot(yaml.load(f, Loader=yaml.FullLoader))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|