configaroo 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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/__init__.py CHANGED
@@ -1,10 +1,17 @@
1
1
  """Bouncy configuration handling"""
2
2
 
3
- from configaroo.configuration import Configuration # noqa
4
- from configaroo.exceptions import ( # noqa
3
+ from configaroo.configuration import Configuration
4
+ from configaroo.exceptions import (
5
5
  ConfigarooException,
6
6
  MissingEnvironmentVariableError,
7
7
  UnsupportedLoaderError,
8
8
  )
9
9
 
10
- __version__ = "0.2.0"
10
+ __all__ = [
11
+ "Configuration",
12
+ "ConfigarooException",
13
+ "MissingEnvironmentVariableError",
14
+ "UnsupportedLoaderError",
15
+ ]
16
+
17
+ __version__ = "0.2.2"
@@ -18,6 +18,19 @@ ModelT = TypeVar("ModelT", bound=BaseModel)
18
18
  class Configuration(UserDict):
19
19
  """A Configuration is a dict-like structure with some conveniences"""
20
20
 
21
+ @classmethod
22
+ def from_dict(cls, data: dict[str, Any] | UserDict[str, Any] | Self) -> Self:
23
+ """Construct a Configuration from a dictionary
24
+
25
+ The dictionary is referenced directly, a copy isn't made
26
+ """
27
+ configuration = cls()
28
+ if isinstance(data, UserDict | Configuration):
29
+ configuration.data = data.data
30
+ else:
31
+ configuration.data = data
32
+ return configuration
33
+
21
34
  @classmethod
22
35
  def from_file(
23
36
  cls,
@@ -54,7 +67,7 @@ class Configuration(UserDict):
54
67
  """Make sure nested sections have type Configuration"""
55
68
  value = self.data[key]
56
69
  if isinstance(value, dict | UserDict | Configuration):
57
- return Configuration(value)
70
+ return Configuration.from_dict(value)
58
71
  else:
59
72
  return value
60
73
 
@@ -67,11 +80,11 @@ class Configuration(UserDict):
67
80
  f"'{type(self).__name__}' has no attribute or key '{key}'"
68
81
  )
69
82
 
70
- def __contains__(self, key: str) -> bool:
83
+ def __contains__(self, key: object) -> bool:
71
84
  """Add support for dotted keys"""
72
85
  if key in self.data:
73
86
  return True
74
- prefix, _, rest = key.partition(".")
87
+ prefix, _, rest = str(key).partition(".")
75
88
  try:
76
89
  return rest in self[prefix]
77
90
  except KeyError:
@@ -108,18 +121,20 @@ class Configuration(UserDict):
108
121
  )
109
122
  return self
110
123
 
111
- def parse_dynamic(self, extra: dict[str, Any] | None = None) -> Self:
124
+ def parse_dynamic(
125
+ self, extra: dict[str, Any] | None = None, _include_self: bool = True
126
+ ) -> Self:
112
127
  """Parse dynamic values of the form {section.key}"""
113
128
  cls = type(self)
114
129
  variables = (
115
- self.to_flat_dict()
130
+ (self.to_flat_dict() if _include_self else {})
116
131
  | {"project_path": _find_pyproject_toml()}
117
132
  | ({} if extra is None else extra)
118
133
  )
119
- return cls(
134
+ parsed = cls(
120
135
  {
121
136
  key: (
122
- value.parse_dynamic(extra=variables)
137
+ value.parse_dynamic(extra=variables, _include_self=False)
123
138
  if isinstance(value, Configuration)
124
139
  else _incomplete_format(value, variables)
125
140
  if isinstance(value, str)
@@ -128,6 +143,10 @@ class Configuration(UserDict):
128
143
  for key, value in self.items()
129
144
  }
130
145
  )
146
+ if parsed == self:
147
+ return parsed
148
+ # Continue parsing until no more replacements are made.
149
+ return parsed.parse_dynamic(extra=extra, _include_self=_include_self)
131
150
 
132
151
  def validate_model(self, model: Type[BaseModel]) -> Self:
133
152
  """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.2
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>
@@ -0,0 +1,12 @@
1
+ configaroo/__init__.py,sha256=dP0lnXS0F6I-6DCLmJGyqiGAhel6dSqWtPbSnmFVe6k,371
2
+ configaroo/configuration.py,sha256=Y942S_IHv4l0drxBH-babalNsKvnfcxEtTpjEt1DP6s,8239
3
+ configaroo/exceptions.py,sha256=1h-6hV7VqqKaRFnu539pjsO0ESSNDibt2kUeF7jAM2M,374
4
+ configaroo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ configaroo/loaders/__init__.py,sha256=-6GAR4g7vYW7Zagq9Ev479kpkfY7kbvDl4JPXd4wQQ0,756
6
+ configaroo/loaders/json.py,sha256=6gs_ZegUEe70vb6uSJfKBos7UjfuJnyWgPE_kjDQISw,258
7
+ configaroo/loaders/toml.py,sha256=ZVbHutZ7V-Z_jf2aHjV18jwaqCXumlr06j48rojHcBM,264
8
+ configaroo-0.2.2.dist-info/licenses/LICENSE,sha256=rdeT6Y5bm0MUaERso7HRWpPj37Y1RD5li2lIQaMNJjc,1090
9
+ configaroo-0.2.2.dist-info/METADATA,sha256=CYD1SBMhbkRAgR0WmBu4UxY7_KDv-wePze5RFfbRtRI,1789
10
+ configaroo-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ configaroo-0.2.2.dist-info/top_level.txt,sha256=JVYICl1cWSjvSOZuZMYm976z9lnZaWtHVRSt373QCxg,11
12
+ configaroo-0.2.2.dist-info/RECORD,,
@@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
17
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
18
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
19
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,12 +0,0 @@
1
- configaroo/__init__.py,sha256=RNKHr1va5QmIdwDkkiGTnF8rR7EJMZZRfPunREdKjE4,255
2
- configaroo/configuration.py,sha256=lEpOBf3qwRFAM0T9Ur9Og1fYy65PzIY6xs1xSNsrHEM,7492
3
- configaroo/exceptions.py,sha256=1h-6hV7VqqKaRFnu539pjsO0ESSNDibt2kUeF7jAM2M,374
4
- configaroo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- configaroo/loaders/__init__.py,sha256=-6GAR4g7vYW7Zagq9Ev479kpkfY7kbvDl4JPXd4wQQ0,756
6
- configaroo/loaders/json.py,sha256=6gs_ZegUEe70vb6uSJfKBos7UjfuJnyWgPE_kjDQISw,258
7
- configaroo/loaders/toml.py,sha256=ZVbHutZ7V-Z_jf2aHjV18jwaqCXumlr06j48rojHcBM,264
8
- configaroo-0.2.0.dist-info/licenses/LICENSE,sha256=2cbzsB4lU8qOO8fO1XVNJD7XPxzPhaWXm6U9DenSc0s,1089
9
- configaroo-0.2.0.dist-info/METADATA,sha256=JfEO1NNJw5qCXIB64Uf1fqdipAlnpkKCpLYpEbfJZGU,1789
10
- configaroo-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
- configaroo-0.2.0.dist-info/top_level.txt,sha256=JVYICl1cWSjvSOZuZMYm976z9lnZaWtHVRSt373QCxg,11
12
- configaroo-0.2.0.dist-info/RECORD,,