configaroo 0.2.0__tar.gz → 0.2.1__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.
Files changed (25) hide show
  1. {configaroo-0.2.0 → configaroo-0.2.1}/PKG-INFO +1 -1
  2. {configaroo-0.2.0 → configaroo-0.2.1}/pyproject.toml +2 -2
  3. configaroo-0.2.1/src/configaroo/__init__.py +17 -0
  4. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/configuration.py +10 -4
  5. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo.egg-info/PKG-INFO +1 -1
  6. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo.egg-info/SOURCES.txt +1 -0
  7. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_configuration.py +7 -48
  8. configaroo-0.2.1/tests/test_dynamic.py +69 -0
  9. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_validation.py +6 -0
  10. configaroo-0.2.0/src/configaroo/__init__.py +0 -10
  11. {configaroo-0.2.0 → configaroo-0.2.1}/LICENSE +0 -0
  12. {configaroo-0.2.0 → configaroo-0.2.1}/README.md +0 -0
  13. {configaroo-0.2.0 → configaroo-0.2.1}/setup.cfg +0 -0
  14. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/exceptions.py +0 -0
  15. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/loaders/__init__.py +0 -0
  16. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/loaders/json.py +0 -0
  17. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/loaders/toml.py +0 -0
  18. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo/py.typed +0 -0
  19. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo.egg-info/dependency_links.txt +0 -0
  20. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo.egg-info/requires.txt +0 -0
  21. {configaroo-0.2.0 → configaroo-0.2.1}/src/configaroo.egg-info/top_level.txt +0 -0
  22. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_environment.py +0 -0
  23. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_json.py +0 -0
  24. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_loaders.py +0 -0
  25. {configaroo-0.2.0 → configaroo-0.2.1}/tests/test_toml.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: configaroo
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Bouncy handling of configuration files
5
5
  Author-email: Geir Arne Hjelle <geirarne@gmail.com>
6
6
  Maintainer-email: Geir Arne Hjelle <geirarne@gmail.com>
@@ -50,13 +50,13 @@ dev = [
50
50
  version = { attr = "configaroo.__version__" }
51
51
 
52
52
  [tool.bumpver]
53
- current_version = "v0.2.0"
53
+ current_version = "v0.2.1"
54
54
  version_pattern = "vMAJOR.MINOR.PATCH"
55
55
  commit_message = "bump version {old_version} -> {new_version}"
56
56
  tag_message = "{new_version}"
57
57
  commit = true
58
58
  tag = true
59
- push = false
59
+ push = true
60
60
 
61
61
  [tool.bumpver.file_patterns]
62
62
  "pyproject.toml" = ['current_version = "{version}"']
@@ -0,0 +1,17 @@
1
+ """Bouncy configuration handling"""
2
+
3
+ from configaroo.configuration import Configuration
4
+ from configaroo.exceptions import (
5
+ ConfigarooException,
6
+ MissingEnvironmentVariableError,
7
+ UnsupportedLoaderError,
8
+ )
9
+
10
+ __all__ = [
11
+ "Configuration",
12
+ "ConfigarooException",
13
+ "MissingEnvironmentVariableError",
14
+ "UnsupportedLoaderError",
15
+ ]
16
+
17
+ __version__ = "0.2.1"
@@ -108,18 +108,20 @@ class Configuration(UserDict):
108
108
  )
109
109
  return self
110
110
 
111
- def parse_dynamic(self, extra: dict[str, Any] | None = None) -> Self:
111
+ def parse_dynamic(
112
+ self, extra: dict[str, Any] | None = None, _include_self: bool = True
113
+ ) -> Self:
112
114
  """Parse dynamic values of the form {section.key}"""
113
115
  cls = type(self)
114
116
  variables = (
115
- self.to_flat_dict()
117
+ (self.to_flat_dict() if _include_self else {})
116
118
  | {"project_path": _find_pyproject_toml()}
117
119
  | ({} if extra is None else extra)
118
120
  )
119
- return cls(
121
+ parsed = cls(
120
122
  {
121
123
  key: (
122
- value.parse_dynamic(extra=variables)
124
+ value.parse_dynamic(extra=variables, _include_self=False)
123
125
  if isinstance(value, Configuration)
124
126
  else _incomplete_format(value, variables)
125
127
  if isinstance(value, str)
@@ -128,6 +130,10 @@ class Configuration(UserDict):
128
130
  for key, value in self.items()
129
131
  }
130
132
  )
133
+ if parsed == self:
134
+ return parsed
135
+ # Continue parsing until no more replacements are made.
136
+ return parsed.parse_dynamic(extra=extra, _include_self=_include_self)
131
137
 
132
138
  def validate_model(self, model: Type[BaseModel]) -> Self:
133
139
  """Validate the configuration against the given model."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: configaroo
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Bouncy handling of configuration files
5
5
  Author-email: Geir Arne Hjelle <geirarne@gmail.com>
6
6
  Maintainer-email: Geir Arne Hjelle <geirarne@gmail.com>
@@ -14,6 +14,7 @@ src/configaroo/loaders/__init__.py
14
14
  src/configaroo/loaders/json.py
15
15
  src/configaroo/loaders/toml.py
16
16
  tests/test_configuration.py
17
+ tests/test_dynamic.py
17
18
  tests/test_environment.py
18
19
  tests/test_json.py
19
20
  tests/test_loaders.py
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
 
5
5
  import pytest
6
6
 
7
+ import configaroo
7
8
  from configaroo import Configuration, configuration
8
9
 
9
10
 
@@ -101,54 +102,6 @@ def test_contains_with_dotted_key(config):
101
102
  assert "nested.number" not in config
102
103
 
103
104
 
104
- def test_parse_dynamic_default(config, file_path):
105
- """Test parsing of default dynamic variables"""
106
- parsed_config = (config | {"diameter": "2 x {nested.pie}"}).parse_dynamic()
107
- print("pyproject.toml dir: ", configuration._find_pyproject_toml(file_path))
108
- print(f"{parsed_config.paths.dynamic = }")
109
- assert parsed_config.paths.dynamic == str(file_path)
110
- assert parsed_config.phrase == "The meaning of life is 42"
111
- assert parsed_config.diameter == "2 x 3.14"
112
-
113
-
114
- def test_parse_dynamic_extra(config, file_path):
115
- """Test parsing of extra dynamic variables"""
116
- parsed_config = (config | {"animal": "{adjective} kangaroo"}).parse_dynamic(
117
- extra={"number": 14, "adjective": "bouncy"}
118
- )
119
- assert parsed_config.paths.dynamic == str(file_path)
120
- assert parsed_config.phrase == "The meaning of life is 14"
121
- assert parsed_config.animal == "bouncy kangaroo"
122
-
123
-
124
- def test_parse_dynamic_formatted(config):
125
- """Test that formatting works for dynamic variables"""
126
- parsed_config = (
127
- config
128
- | {
129
- "string": "Hey {word!r}",
130
- "three": "->{nested.pie:6.0f}<-",
131
- "centered": "|{word:^12}|",
132
- }
133
- ).parse_dynamic()
134
- assert parsed_config.centered == "| platypus |"
135
- assert parsed_config.three == "-> 3<-"
136
- assert parsed_config.string == "Hey 'platypus'"
137
-
138
-
139
- def test_parse_dynamic_ignore(config):
140
- """Test that parsing of dynamic variables ignores unknown replacements"""
141
- parsed_config = (
142
- config
143
- | {
144
- "animal": "{adjective} kangaroo",
145
- "phrase": "one {nested.non_existent} dollar",
146
- }
147
- ).parse_dynamic()
148
- assert parsed_config.animal == "{adjective} kangaroo"
149
- assert parsed_config.phrase == "one {nested.non_existent} dollar"
150
-
151
-
152
105
  def test_find_pyproject_toml():
153
106
  """Test that the pyproject.toml file can be located"""
154
107
  assert configuration._find_pyproject_toml() == Path(__file__).parent.parent
@@ -166,3 +119,9 @@ def test_incomplete_formatter():
166
119
  {"number": 3.14, "string": "platypus", "name": "Geir Arne"},
167
120
  )
168
121
  assert formatted == " 3.1 {non_existent} 'platypus' Geir Arne"
122
+
123
+
124
+ def test_public_classes_are_exposed():
125
+ """Test that the __all__ attribute exposes all public classes"""
126
+ public_classes = [attr for attr in dir(configaroo) if "A" <= attr[:1] <= "Z"]
127
+ assert sorted(public_classes) == sorted(configaroo.__all__)
@@ -0,0 +1,69 @@
1
+ """Test handling of dynamic variables"""
2
+
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+
7
+
8
+ @pytest.fixture
9
+ def file_path():
10
+ """The path to the current file"""
11
+ return Path(__file__).resolve()
12
+
13
+
14
+ def test_parse_dynamic_default(config, file_path):
15
+ """Test parsing of default dynamic variables"""
16
+ parsed_config = (config | {"diameter": "2 x {nested.pie}"}).parse_dynamic()
17
+ assert parsed_config.paths.dynamic == str(file_path)
18
+ assert parsed_config.phrase == "The meaning of life is 42"
19
+ assert parsed_config.diameter == "2 x 3.14"
20
+
21
+
22
+ def test_parse_dynamic_extra(config, file_path):
23
+ """Test parsing of extra dynamic variables"""
24
+ parsed_config = (config | {"animal": "{adjective} kangaroo"}).parse_dynamic(
25
+ extra={"number": 14, "adjective": "bouncy"}
26
+ )
27
+ assert parsed_config.paths.dynamic == str(file_path)
28
+ assert parsed_config.phrase == "The meaning of life is 14"
29
+ assert parsed_config.animal == "bouncy kangaroo"
30
+
31
+
32
+ def test_parse_dynamic_formatted(config):
33
+ """Test that formatting works for dynamic variables"""
34
+ parsed_config = (
35
+ config
36
+ | {
37
+ "string": "Hey {word!r}",
38
+ "three": "->{nested.pie:6.0f}<-",
39
+ "centered": "|{word:^12}|",
40
+ }
41
+ ).parse_dynamic()
42
+ assert parsed_config.centered == "| platypus |"
43
+ assert parsed_config.three == "-> 3<-"
44
+ assert parsed_config.string == "Hey 'platypus'"
45
+
46
+
47
+ def test_parse_dynamic_ignore(config):
48
+ """Test that parsing of dynamic variables ignores unknown replacements"""
49
+ parsed_config = (
50
+ config
51
+ | {
52
+ "animal": "{adjective} kangaroo",
53
+ "phrase": "one {nested.non_existent} dollar",
54
+ }
55
+ ).parse_dynamic()
56
+ assert parsed_config.animal == "{adjective} kangaroo"
57
+ assert parsed_config.phrase == "one {nested.non_existent} dollar"
58
+
59
+
60
+ def test_parse_dynamic_nested(config, file_path):
61
+ """Test that parsing dynamic variables referring to other dynamic variables work"""
62
+ parsed_config = config.parse_dynamic()
63
+ assert parsed_config.paths.nested == str(file_path)
64
+
65
+
66
+ def test_parse_dynamic_only_full_name(config):
67
+ """Test that parsing dynamic variables only use full dotted name"""
68
+ parsed_config = config.parse_dynamic()
69
+ assert parsed_config.log.format == config.log.format
@@ -53,3 +53,9 @@ def test_validate_and_convert(config, model):
53
53
  config_w_model = config.with_model(model)
54
54
  assert isinstance(config_w_model, pydantic.BaseModel)
55
55
  assert isinstance(config_w_model.paths.relative, Path)
56
+
57
+
58
+ def test_convert_to_path(config, model):
59
+ paths_cfg = config.parse_dynamic().with_model(model).paths
60
+ assert isinstance(paths_cfg.relative, Path) and paths_cfg.relative.exists()
61
+ assert isinstance(paths_cfg.directory, Path) and paths_cfg.directory.is_dir()
@@ -1,10 +0,0 @@
1
- """Bouncy configuration handling"""
2
-
3
- from configaroo.configuration import Configuration # noqa
4
- from configaroo.exceptions import ( # noqa
5
- ConfigarooException,
6
- MissingEnvironmentVariableError,
7
- UnsupportedLoaderError,
8
- )
9
-
10
- __version__ = "0.2.0"
File without changes
File without changes
File without changes