configaroo 0.3.0__tar.gz → 0.4.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.
- {configaroo-0.3.0/src/configaroo.egg-info → configaroo-0.4.0}/PKG-INFO +1 -1
- {configaroo-0.3.0 → configaroo-0.4.0}/pyproject.toml +1 -1
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/__init__.py +1 -1
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/configuration.py +15 -26
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/loaders/__init__.py +6 -1
- {configaroo-0.3.0 → configaroo-0.4.0/src/configaroo.egg-info}/PKG-INFO +1 -1
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_configuration.py +0 -6
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_json.py +6 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_toml.py +6 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/LICENSE +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/README.md +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/setup.cfg +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/exceptions.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/loaders/json.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/loaders/toml.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo/py.typed +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo.egg-info/SOURCES.txt +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo.egg-info/dependency_links.txt +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo.egg-info/requires.txt +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/src/configaroo.egg-info/top_level.txt +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_dynamic.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_environment.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_loaders.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_print.py +0 -0
- {configaroo-0.3.0 → configaroo-0.4.0}/tests/test_validation.py +0 -0
@@ -79,7 +79,7 @@ python_version = "3.11"
|
|
79
79
|
strict = true
|
80
80
|
|
81
81
|
[tool.bumpver]
|
82
|
-
current_version = "v0.
|
82
|
+
current_version = "v0.4.0"
|
83
83
|
version_pattern = "vMAJOR.MINOR.PATCH"
|
84
84
|
commit_message = "bump version {old_version} -> {new_version}"
|
85
85
|
tag_message = "{new_version}"
|
@@ -36,33 +36,20 @@ class Configuration(UserDict[str, Any]):
|
|
36
36
|
def from_file(
|
37
37
|
cls,
|
38
38
|
file_path: str | Path,
|
39
|
+
*,
|
39
40
|
loader: str | None = None,
|
40
|
-
|
41
|
-
env_prefix: str = "",
|
42
|
-
extra_dynamic: dict[str, Any] | None = None,
|
41
|
+
not_exist_ok: bool = False,
|
43
42
|
) -> Self:
|
44
|
-
"""Read a Configuration from a file.
|
45
|
-
config_dict = loaders.from_file(file_path, loader=loader)
|
46
|
-
return cls(config_dict).initialize(
|
47
|
-
envs=envs, env_prefix=env_prefix, extra_dynamic=extra_dynamic
|
48
|
-
)
|
49
|
-
|
50
|
-
def initialize(
|
51
|
-
self,
|
52
|
-
envs: dict[str, str] | None = None,
|
53
|
-
env_prefix: str = "",
|
54
|
-
extra_dynamic: dict[str, Any] | None = None,
|
55
|
-
) -> Self:
|
56
|
-
"""Initialize a configuration.
|
43
|
+
"""Read a Configuration from a file.
|
57
44
|
|
58
|
-
|
45
|
+
If not_exist_ok is True, then a missing file returns an empty
|
46
|
+
configuration. This may be useful if the configuration is potentially
|
47
|
+
populated by environment variables.
|
59
48
|
"""
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
"""Apply a pydantic model to a configuration."""
|
65
|
-
return self.validate_model(model).convert_model(model)
|
49
|
+
config_dict = loaders.from_file(
|
50
|
+
file_path, loader=loader, not_exist_ok=not_exist_ok
|
51
|
+
)
|
52
|
+
return cls(config_dict)
|
66
53
|
|
67
54
|
def __getitem__(self, key: str) -> Any: # noqa: ANN401
|
68
55
|
"""Make sure nested sections have type Configuration."""
|
@@ -172,6 +159,10 @@ class Configuration(UserDict[str, Any]):
|
|
172
159
|
"""Convert data types to match the given model."""
|
173
160
|
return model(**self.data)
|
174
161
|
|
162
|
+
def with_model(self, model: type[ModelT]) -> ModelT:
|
163
|
+
"""Apply a pydantic model to a configuration."""
|
164
|
+
return self.validate_model(model).convert_model(model)
|
165
|
+
|
175
166
|
def to_dict(self) -> dict[str, Any]:
|
176
167
|
"""Dump the configuration into a Python dictionary."""
|
177
168
|
return {
|
@@ -217,9 +208,7 @@ def _get_rich_print() -> Callable[[str], None]: # pragma: no cover
|
|
217
208
|
|
218
209
|
return Console().print
|
219
210
|
except ImportError:
|
220
|
-
|
221
|
-
|
222
|
-
return builtins.print
|
211
|
+
return print
|
223
212
|
|
224
213
|
|
225
214
|
def _print_dict_as_tree(
|
@@ -26,9 +26,14 @@ def loader_names() -> list[str]:
|
|
26
26
|
return sorted(pyplugs.names(PACKAGE))
|
27
27
|
|
28
28
|
|
29
|
-
def from_file(
|
29
|
+
def from_file(
|
30
|
+
path: str | Path, *, loader: str | None = None, not_exist_ok: bool = False
|
31
|
+
) -> dict[str, Any]:
|
30
32
|
"""Load a file using a loader defined by the suffix if necessary."""
|
31
33
|
path = Path(path)
|
34
|
+
if not path.exists() and not_exist_ok:
|
35
|
+
return {}
|
36
|
+
|
32
37
|
loader = path.suffix.lstrip(".") if loader is None else loader
|
33
38
|
try:
|
34
39
|
return load(loader, path=path)
|
@@ -8,12 +8,6 @@ import configaroo
|
|
8
8
|
from configaroo import Configuration, configuration
|
9
9
|
|
10
10
|
|
11
|
-
@pytest.fixture
|
12
|
-
def file_path() -> Path:
|
13
|
-
"""Return the path to the current file."""
|
14
|
-
return Path(__file__).resolve()
|
15
|
-
|
16
|
-
|
17
11
|
def test_read_simple_values_as_attributes(config: Configuration) -> None:
|
18
12
|
"""Test attribute access for simple values."""
|
19
13
|
assert config.number == 42
|
@@ -38,6 +38,12 @@ def test_error_on_wrong_format(toml_path: Path) -> None:
|
|
38
38
|
Configuration.from_file(toml_path, loader="json")
|
39
39
|
|
40
40
|
|
41
|
+
def test_file_may_be_allowed_to_not_exist() -> None:
|
42
|
+
"""Test that not_exist_ok can suppress error when file doesn't exist."""
|
43
|
+
config = Configuration.from_file("non-existent.json", not_exist_ok=True)
|
44
|
+
assert config.data == {}
|
45
|
+
|
46
|
+
|
41
47
|
def test_can_read_json_values(json_path: Path) -> None:
|
42
48
|
"""Test that values can be accessed."""
|
43
49
|
config = Configuration.from_file(json_path)
|
@@ -38,6 +38,12 @@ def test_error_on_wrong_format(json_path: Path) -> None:
|
|
38
38
|
Configuration.from_file(json_path, loader="toml")
|
39
39
|
|
40
40
|
|
41
|
+
def test_file_may_be_allowed_to_not_exist() -> None:
|
42
|
+
"""Test that not_exist_ok can suppress error when file doesn't exist."""
|
43
|
+
config = Configuration.from_file("non-existent.toml", not_exist_ok=True)
|
44
|
+
assert config.data == {}
|
45
|
+
|
46
|
+
|
41
47
|
def test_can_read_toml_values(toml_path: Path) -> None:
|
42
48
|
"""Test that values can be accessed."""
|
43
49
|
config = Configuration.from_file(toml_path)
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|