appsettings2 1.3.7__tar.gz → 2.0.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 (26) hide show
  1. {appsettings2-1.3.7/src/appsettings2.egg-info → appsettings2-2.0.1}/PKG-INFO +13 -13
  2. {appsettings2-1.3.7 → appsettings2-2.0.1}/README.md +8 -8
  3. {appsettings2-1.3.7 → appsettings2-2.0.1}/pyproject.toml +12 -5
  4. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/Configuration.py +107 -72
  5. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/ConfigurationBuilder.py +59 -27
  6. appsettings2-2.0.1/src/appsettings2/ConfigurationException.py +12 -0
  7. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/__init__.py +8 -5
  8. appsettings2-2.0.1/src/appsettings2/helpers.py +44 -0
  9. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/CommandLineConfigurationProvider.py +8 -8
  10. appsettings2-2.0.1/src/appsettings2/providers/ConfigurationProvider.py +20 -0
  11. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/EnvironmentConfigurationProvider.py +3 -4
  12. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/JsonConfigurationProvider.py +29 -27
  13. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/TomlConfigurationProvider.py +27 -26
  14. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/YamlConfigurationProvider.py +30 -25
  15. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/providers/__init__.py +1 -0
  16. {appsettings2-1.3.7 → appsettings2-2.0.1/src/appsettings2.egg-info}/PKG-INFO +13 -13
  17. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2.egg-info/requires.txt +3 -0
  18. appsettings2-1.3.7/src/appsettings2/ConfigurationException.py +0 -10
  19. appsettings2-1.3.7/src/appsettings2/helpers.py +0 -29
  20. appsettings2-1.3.7/src/appsettings2/providers/ConfigurationProvider.py +0 -17
  21. {appsettings2-1.3.7 → appsettings2-2.0.1}/LICENSE +0 -0
  22. {appsettings2-1.3.7 → appsettings2-2.0.1}/setup.cfg +0 -0
  23. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2/py.typed +0 -0
  24. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2.egg-info/SOURCES.txt +0 -0
  25. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2.egg-info/dependency_links.txt +0 -0
  26. {appsettings2-1.3.7 → appsettings2-2.0.1}/src/appsettings2.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: appsettings2
3
- Version: 1.3.7
3
+ Version: 2.0.1
4
4
  Summary: Unifies configuration sources into a Configuration object that can be bound to complex types, or accessed directly for configuration data.
5
5
  Author-email: Shaun Wilson <mrshaunwilson@msn.com>
6
6
  License: MIT License
@@ -31,10 +31,7 @@ Project-URL: Repository, https://github.com/wilson0x4d/appsettings2.git
31
31
  Keywords: appsettings,configuration
32
32
  Classifier: Intended Audience :: Developers
33
33
  Classifier: Operating System :: OS Independent
34
- Classifier: Programming Language :: Python :: 3.11
35
- Classifier: Programming Language :: Python :: 3.12
36
- Classifier: Programming Language :: Python :: 3.13
37
- Classifier: Programming Language :: Python :: 3.14
34
+ Classifier: Programming Language :: Python
38
35
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
39
36
  Requires-Python: >=3.11
40
37
  Description-Content-Type: text/markdown
@@ -42,7 +39,10 @@ License-File: LICENSE
42
39
  Requires-Dist: pyyaml>=6.0.2
43
40
  Provides-Extra: dev
44
41
  Requires-Dist: coverage; extra == "dev"
42
+ Requires-Dist: flake8; extra == "dev"
43
+ Requires-Dist: flake8-pyproject; extra == "dev"
45
44
  Requires-Dist: mypy; extra == "dev"
45
+ Requires-Dist: pep8-naming; extra == "dev"
46
46
  Requires-Dist: punit>=1.4.0; extra == "dev"
47
47
  Requires-Dist: twine; extra == "dev"
48
48
  Requires-Dist: types-PyYAML; extra == "dev"
@@ -69,9 +69,9 @@ from appsettings2 import *
69
69
  from appsettings2.providers import *
70
70
 
71
71
  config = ConfigurationBuilder()\
72
- .addProvider(JsonConfigurationProvider(f'appsettings.json'))\
73
- .addProvider(JsonConfigurationProvider(f'appsettings.Development.json', required=False))\
74
- .addProvider(EnvironmentConfigurationProvider())\
72
+ .add_provider(JsonConfigurationProvider(f'appsettings.json'))\
73
+ .add_provider(JsonConfigurationProvider(f'appsettings.Development.json', required=False))\
74
+ .add_provider(EnvironmentConfigurationProvider())\
75
75
  .build()
76
76
 
77
77
  print(config)
@@ -140,7 +140,7 @@ class AppSettings:
140
140
  MaxBatchSize:int
141
141
 
142
142
  configuration = ConfigurationBuilder()\
143
- .addProvider(JsonConfigurationProvider(json=json))
143
+ .add_provider(JsonConfigurationProvider(json=json))
144
144
  .build()
145
145
 
146
146
  settings = AppSettings()
@@ -184,7 +184,7 @@ print(d)
184
184
 
185
185
  ### Custom Provider Development
186
186
 
187
- You can implement custom Configuration Providers by subclassing `ConfigurationProvider` and implementing `populateConfiguration(...)`.
187
+ You can implement custom Configuration Providers by subclassing `ConfigurationProvider` and implementing `populate_configuration(...)`.
188
188
 
189
189
  For a peek at the simplicity of provider implementation, this is `ConfigurationProvider`:
190
190
 
@@ -192,7 +192,7 @@ For a peek at the simplicity of provider implementation, this is `ConfigurationP
192
192
  class ConfigurationProvider(abstract):
193
193
 
194
194
  @abstractmethod
195
- def populateConfiguration(self, configuration:Configuration) -> None:
195
+ def populate_configuration(self, configuration:Configuration) -> None:
196
196
  """The ConfigurationProvider will populate the provided Configuration instance."""
197
197
  pass
198
198
  ```
@@ -206,10 +206,10 @@ There are several helpers available which simplify loading configurations. Consi
206
206
  ```python
207
207
  import appsettings2
208
208
 
209
- config = appsettings2.getConfiguration()
209
+ config = appsettings2.get_configuration()
210
210
  ```
211
211
 
212
- You can read more about `getConfiguration` in [the docs](https://appsettings2.readthedocs.io/en/latest/ref/helpers/getConfiguration.html).
212
+ You can read more about `get_configuration` in [the docs](https://appsettings2.readthedocs.io/en/latest/ref/helpers/get_configuration.html).
213
213
 
214
214
  ## Contact
215
215
 
@@ -19,9 +19,9 @@ from appsettings2 import *
19
19
  from appsettings2.providers import *
20
20
 
21
21
  config = ConfigurationBuilder()\
22
- .addProvider(JsonConfigurationProvider(f'appsettings.json'))\
23
- .addProvider(JsonConfigurationProvider(f'appsettings.Development.json', required=False))\
24
- .addProvider(EnvironmentConfigurationProvider())\
22
+ .add_provider(JsonConfigurationProvider(f'appsettings.json'))\
23
+ .add_provider(JsonConfigurationProvider(f'appsettings.Development.json', required=False))\
24
+ .add_provider(EnvironmentConfigurationProvider())\
25
25
  .build()
26
26
 
27
27
  print(config)
@@ -90,7 +90,7 @@ class AppSettings:
90
90
  MaxBatchSize:int
91
91
 
92
92
  configuration = ConfigurationBuilder()\
93
- .addProvider(JsonConfigurationProvider(json=json))
93
+ .add_provider(JsonConfigurationProvider(json=json))
94
94
  .build()
95
95
 
96
96
  settings = AppSettings()
@@ -134,7 +134,7 @@ print(d)
134
134
 
135
135
  ### Custom Provider Development
136
136
 
137
- You can implement custom Configuration Providers by subclassing `ConfigurationProvider` and implementing `populateConfiguration(...)`.
137
+ You can implement custom Configuration Providers by subclassing `ConfigurationProvider` and implementing `populate_configuration(...)`.
138
138
 
139
139
  For a peek at the simplicity of provider implementation, this is `ConfigurationProvider`:
140
140
 
@@ -142,7 +142,7 @@ For a peek at the simplicity of provider implementation, this is `ConfigurationP
142
142
  class ConfigurationProvider(abstract):
143
143
 
144
144
  @abstractmethod
145
- def populateConfiguration(self, configuration:Configuration) -> None:
145
+ def populate_configuration(self, configuration:Configuration) -> None:
146
146
  """The ConfigurationProvider will populate the provided Configuration instance."""
147
147
  pass
148
148
  ```
@@ -156,10 +156,10 @@ There are several helpers available which simplify loading configurations. Consi
156
156
  ```python
157
157
  import appsettings2
158
158
 
159
- config = appsettings2.getConfiguration()
159
+ config = appsettings2.get_configuration()
160
160
  ```
161
161
 
162
- You can read more about `getConfiguration` in [the docs](https://appsettings2.readthedocs.io/en/latest/ref/helpers/getConfiguration.html).
162
+ You can read more about `get_configuration` in [the docs](https://appsettings2.readthedocs.io/en/latest/ref/helpers/get_configuration.html).
163
163
 
164
164
  ## Contact
165
165
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "appsettings2"
3
- version = "1.3.7"
3
+ version = "2.0.1"
4
4
  description = "Unifies configuration sources into a Configuration object that can be bound to complex types, or accessed directly for configuration data."
5
5
  keywords = ["appsettings", "configuration"]
6
6
  authors = [
@@ -11,10 +11,7 @@ license = {file = "LICENSE"}
11
11
  classifiers = [
12
12
  "Intended Audience :: Developers",
13
13
  "Operating System :: OS Independent",
14
- "Programming Language :: Python :: 3.11",
15
- "Programming Language :: Python :: 3.12",
16
- "Programming Language :: Python :: 3.13",
17
- "Programming Language :: Python :: 3.14",
14
+ "Programming Language :: Python",
18
15
  "Topic :: Software Development :: Libraries :: Python Modules"
19
16
  ]
20
17
  requires-python = ">=3.11"
@@ -25,7 +22,10 @@ dependencies = [
25
22
  [project.optional-dependencies]
26
23
  dev = [
27
24
  "coverage",
25
+ "flake8",
26
+ "flake8-pyproject",
28
27
  "mypy",
28
+ "pep8-naming",
29
29
  "punit (>=1.4.0)",
30
30
  "twine",
31
31
  "types-PyYAML"
@@ -50,3 +50,10 @@ exclude = [
50
50
 
51
51
  [tool.setuptools.package-data]
52
52
  "appsettings2" = ["py.typed"]
53
+
54
+ [tool.flake8]
55
+ max-line-length = 120
56
+ ignore = ["D100","E501"]
57
+ per-file-ignore = [
58
+ "tests/*.py:D012",
59
+ ]
@@ -6,48 +6,54 @@ import json
6
6
  import re
7
7
  import types
8
8
  import typing
9
- from typing import Any, TYPE_CHECKING
9
+ from typing import Any, Iterator, TYPE_CHECKING
10
10
  import unicodedata
11
11
 
12
12
  from .ConfigurationException import ConfigurationException
13
13
 
14
14
 
15
15
  class Configuration:
16
- """
17
- The :py:class:`~appsettings2.Configuration` class is how applications access configuration data populated by :py:class:`~appsettings2.providers.ConfigurationProvider` objects. It exposes configuration data through dynamic object attributes as well as a dictionary-like interface.
18
- """
16
+ """The :py:class:`~appsettings2.Configuration` class is how applications access configuration data populated by :py:class:`~appsettings2.providers.ConfigurationProvider` objects. It exposes configuration data through dynamic object attributes as well as a dictionary-like interface."""
19
17
 
20
- __key_scrub_re:re.Pattern|None
21
- __keys:dict[str, str]
22
- __normalize:bool
18
+ __key_scrub_re: re.Pattern | None
19
+ __keys: dict[str, str]
20
+ __normalize: bool
23
21
 
24
- def __init__(self, *, normalize:bool = False, scrubkeys:bool = False):
22
+ def __init__(self, normalize: bool = False, scrubkeys: bool = False) -> None:
25
23
  """
24
+ Initialize *Configuration* instance.
25
+
26
26
  :param normalize: Option indicating whether or not attribute names should be normalized to upper-case on the resulting :py:class:`~appsettings2.Configuration` object, defaults to False.
27
27
  :param scrubkeys: Option indicating whether or not attribute names should be scrubbed to be compatible with the Python lexer, defaults to False.
28
28
  """
29
29
  self.__keys = {}
30
30
  self.__logger = logging.getLogger('appsettings2')
31
31
  self.__normalize = normalize
32
- self.__key_scrub_re = None if not scrubkeys else re.compile(r'[^A-Za-z0-9_]', re.IGNORECASE | re.UNICODE)
32
+ self.__key_scrub_re = None if not scrubkeys else re.compile(
33
+ r'[^A-Za-z0-9_]', re.IGNORECASE | re.UNICODE)
33
34
 
34
35
  if TYPE_CHECKING:
35
- # This tells mypy that accessing any attribute returns 'Any'
36
- def __getattr__(self, name: str) -> Any: ...
37
-
36
+
37
+ def __getattr__(self, name: str) -> Any:
38
+ """Tell type checkers that accessing any attribute returns any type."""
39
+ ...
40
+
38
41
  # This tells mypy that setting any attribute is allowed
39
- def __setattr__(self, name: str, value: Any) -> None: ...
42
+ def __setattr__(self, name: str, value: Any) -> None:
43
+ """Tell type checkers that setting any attribute to any value is allowed."""
44
+ ...
40
45
 
41
- def __delitem__(self, key:str) -> None:
46
+ def __delitem__(self, key: str) -> None:
47
+ """Delete the specified configuration key."""
42
48
  key = key.upper()
43
49
  k = self.__keys.get(key)
44
50
  if k is not None:
45
51
  delattr(self, k)
46
52
  self.__keys.pop(key)
47
53
 
48
- def __getitem__(self, key:str) -> Any:
54
+ def __getitem__(self, key: str) -> Any:
49
55
  """
50
- Gets the configuration data associated with the specified `key`.
56
+ Get the configuration data associated with the specified configuration key.
51
57
 
52
58
  :param key: The configuration key to get data for. Supports `__` and `:` hierarchical delimiters.
53
59
  :return: The configuration data associated with `key`, otherwise raises `KeyError` if `key` was not found.
@@ -65,27 +71,31 @@ class Configuration:
65
71
  o = o[part]
66
72
  return o
67
73
 
68
- def __iter__(self):
74
+ def __iter__(self) -> Iterator[str]:
75
+ """Iterate configuration keys."""
69
76
  return iter(self.__keys.values())
70
77
 
71
78
  def __len__(self) -> int:
79
+ """Get the number of configuration keys."""
72
80
  return len(self.__keys)
73
81
 
74
- def __recursiveBind(self, target:object, source:'Configuration|dict') -> Any:
82
+ def __recursive_bind(self, target: object, source: 'Configuration|dict') -> Any:
75
83
  if target is None:
76
84
  return None
77
85
  if hasattr(target, '__class__'):
78
- targetTypeHints = typing.get_type_hints(getattr(target, '__class__'))
86
+ target_type_hints = typing.get_type_hints(
87
+ getattr(target, '__class__'))
79
88
  else:
80
- targetTypeHints = typing.get_type_hints(target)
81
- names = set(dir(target) | targetTypeHints.keys())
89
+ target_type_hints = typing.get_type_hints(target)
90
+ names = set(dir(target) | target_type_hints.keys())
82
91
  for aname in names:
83
92
  if aname.startswith('_'):
84
93
  continue
85
- lval = None if not hasattr(target, aname) else getattr(target, aname)
94
+ lval = None if not hasattr(
95
+ target, aname) else getattr(target, aname)
86
96
  if isinstance(lval, types.FunctionType) or isinstance(lval, types.MethodType):
87
97
  continue
88
- ahint = targetTypeHints.get(aname)
98
+ ahint = target_type_hints.get(aname)
89
99
  rval = source.get(aname)
90
100
  if ahint is None:
91
101
  # attr has no type hints, attempt to treat as a property
@@ -95,7 +105,8 @@ class Configuration:
95
105
  lval = getattr(target, aname)
96
106
  except AttributeError:
97
107
  lval = None
98
- self.__logger.debug(f'Failed to bind {aname}', exc_info=True)
108
+ self.__logger.debug(
109
+ f'Failed to bind {aname}', exc_info=True)
99
110
  if (not hasattr(prop, 'fset') or getattr(prop, 'fset') is None):
100
111
  # NOTE: lval is not settable
101
112
  if rval is None:
@@ -107,7 +118,8 @@ class Configuration:
107
118
  continue
108
119
  elif not (issubclass(type(lval), list) and issubclass(type(rval), list)):
109
120
  # non-list values cannot be merged
110
- raise Exception(f'Cannot bind `None` to attribute `{aname}`')
121
+ raise Exception(
122
+ f'Cannot bind `None` to attribute `{aname}`')
111
123
  phints = typing.get_type_hints(getattr(prop, 'fget'))
112
124
  if phints is None or (not issubclass(type(phints), dict)):
113
125
  # NOTE: can't get hints from getter, can't bind
@@ -132,60 +144,64 @@ class Configuration:
132
144
  if lval is None:
133
145
  lval = ahint()
134
146
  setattr(target, aname, lval)
135
- self.__recursiveBind(lval, rval)
147
+ self.__recursive_bind(lval, rval)
136
148
  elif typing.get_origin(ahint) is list:
137
- elementType = ahint.__args__[0]
149
+ element_type = ahint.__args__[0]
138
150
  if lval is None:
139
151
  lval = ahint()
140
152
  setattr(target, aname, lval)
141
153
  for e in rval:
142
154
  lval.append(
143
- self.__recursiveBindType(elementType, e)
155
+ self.__recursive_bind_type(element_type, e)
144
156
  )
145
157
  else:
146
158
  setattr(target, aname, rval)
147
159
  return target
148
160
 
149
- def __recursiveBindType(self, elementType:type, source:Any) -> Any:
150
- if isinstance(source, elementType):
161
+ def __recursive_bind_type(self, element_type: type, source: Any) -> Any:
162
+ if isinstance(source, element_type):
151
163
  return source
152
- elif elementType is float:
164
+ elif element_type is float:
153
165
  return float(source)
154
- elif elementType is int:
166
+ elif element_type is int:
155
167
  return int(source)
156
- elif elementType is str:
168
+ elif element_type is str:
157
169
  return str(source)
158
170
  elif isinstance(source, Configuration | dict):
159
- v = elementType()
160
- return self.__recursiveBind(v, source)
171
+ v = element_type()
172
+ return self.__recursive_bind(v, source)
161
173
  else:
162
- raise ConfigurationException(f'Recursive bind to type `{elementType}` from `{type(source)}` is not supported.')
174
+ raise ConfigurationException(
175
+ f'Recursive bind to type `{element_type}` from `{type(source)}` is not supported.')
163
176
 
164
- def __scrub_key(self, key:str) -> str:
177
+ def __scrub_key(self, key: str) -> str:
165
178
  """Scrubs a key for use as an attribute/identifier according to the Python lexer/standard."""
166
179
  key = key.replace(':', '__').replace('.', '_')
167
180
  return key if self.__key_scrub_re is None else self.__key_scrub_re.sub(
168
- self.__scrub_uc,
169
- unicodedata.normalize(
170
- 'NFKC',
171
- key))
181
+ self.__scrub_uc,
182
+ unicodedata.normalize(
183
+ 'NFKC',
184
+ key))
172
185
 
173
- def __scrub_uc(self, m:re.Match) -> str:
186
+ def __scrub_uc(self, m: re.Match) -> str:
174
187
  match unicodedata.category(m[0]):
175
- case 'Lu' | 'Ll' | 'Lt' | 'Lm' | 'Lo' | 'Nl' | 'Mn' | 'Mc' | 'Nd' | 'Pc' :
188
+ case 'Lu' | 'Ll' | 'Lt' | 'Lm' | 'Lo' | 'Nl' | 'Mn' | 'Mc' | 'Nd' | 'Pc':
176
189
  return m[0]
177
190
  case _:
178
191
  return '_'
179
192
 
180
- def __setitem__(self, key:str, value:Any) -> None:
193
+ def __setitem__(self, key: str, value: Any) -> None:
194
+ """Set configuration key to specified *value*."""
181
195
  self.set(key, value)
182
196
 
183
197
  def __str__(self) -> str:
184
- return json.dumps(self.toDictionary())
198
+ """Render the configuration as a JSON string."""
199
+ return json.dumps(self.to_dict(), indent=None, ensure_ascii=False)
185
200
 
186
- def bind(self, target:object, key:str|None = None) -> Any:
201
+ def bind(self, target: object, key: str | None = None) -> Any:
187
202
  """
188
203
  Binds the configuration values into the target object.
204
+
189
205
  Can optionally specify a configuration key to bind from.
190
206
 
191
207
  :param target: The object to bind configuration data into.
@@ -195,43 +211,50 @@ class Configuration:
195
211
  if target is None:
196
212
  raise ConfigurationException('Missing required argument: target')
197
213
  if key is None:
198
- return self.__recursiveBind(target, self)
214
+ return self.__recursive_bind(target, self)
199
215
  else:
200
216
  source = self.get(key)
201
217
  if source is not None:
202
- sourceType = type(source)
203
- if sourceType is Configuration or sourceType is dict:
204
- return self.__recursiveBind(target, source)
218
+ source_type = type(source)
219
+ if source_type is Configuration or source_type is dict:
220
+ return self.__recursive_bind(target, source)
205
221
  else:
206
- raise ConfigurationException(f'Bind of source type `{type(source)}` is not supported.')
222
+ raise ConfigurationException(
223
+ f'Bind of source type `{type(source)}` is not supported.')
207
224
  return target
208
225
 
209
226
  def clear(self) -> None:
227
+ """Clear all configuration data."""
210
228
  while len(self.__keys) > 0:
211
229
  t = self.__keys.popitem()
212
230
  delattr(self, t[1])
213
231
 
214
232
  @staticmethod
215
- def fromDictionary(source:dict, *, normalize:bool = False, scrubkeys:bool = False) -> 'Configuration':
233
+ def from_dict(source: dict, normalize: bool = False, scrubkeys: bool = False) -> 'Configuration':
216
234
  """
217
- Constructs a :py:class:`~appsettings2.Configuration` instance from the supplied dictionary `source`.
235
+ Construct a :py:class:`~appsettings2.Configuration` instance from the supplied dictionary `source`.
218
236
 
219
237
  :param source: The dictionary object to populate from.
220
238
  :param normalize: Option indicating whether or not attribute names should be normalized to upper-case on the resulting :py:class:`~appsettings2.Configuration` object, defaults to False.
221
239
  :param scrubkeys: Option indicating whether or not attribute names should be scrubbed to be compatible with the Python lexer, defaults to False.
222
240
  :return: A :py:class:`~appsettings2.Configuration` object derived from the `source` parameter.
223
241
  """
224
- config:Configuration = Configuration(normalize=normalize, scrubkeys=scrubkeys)
242
+ config: Configuration = Configuration(
243
+ normalize=normalize, scrubkeys=scrubkeys)
225
244
  for kvp in source.items():
226
245
  v = kvp[1]
227
246
  if issubclass(type(v), dict):
228
- v = Configuration.fromDictionary(v, normalize=normalize, scrubkeys=scrubkeys)
247
+ v = Configuration.from_dict(
248
+ v, normalize=normalize, scrubkeys=scrubkeys)
229
249
  config.set(kvp[0], v)
230
250
  return config
231
251
 
232
- def get(self, key:str, default:Any = None) -> Any:
252
+ fromDictionary = from_dict # noqa: N815
253
+ """⚠️ DEPRECATED: use ``from_dict(...)`` instead."""
254
+
255
+ def get(self, key: str, default: Any = None) -> Any:
233
256
  """
234
- Gets the configuration data associated with the specified `key`.
257
+ Get the configuration data associated with the specified `key`.
235
258
 
236
259
  :param key: The configuration key to get data for. Supports `__` and `:` hierarchical delimiters.
237
260
  :param default: The value to be returned if `key` does not exist, defaults to None
@@ -250,10 +273,12 @@ class Configuration:
250
273
  o = o.get(part, default)
251
274
  return o
252
275
 
253
- def has_key(self, key:str) -> bool:
276
+ def has_key(self, key: str) -> bool:
277
+ """Check for a specific configuration key."""
254
278
  return self.__keys.get(key.upper()) is not None
255
279
 
256
- def items(self) -> list[tuple[str,Any]]:
280
+ def items(self) -> list[tuple[str, Any]]:
281
+ """Get all key-value pairs as individal ``tuple`` items."""
257
282
  it = []
258
283
  for k in self.keys():
259
284
  v = self.get(k)
@@ -261,19 +286,21 @@ class Configuration:
261
286
  return it
262
287
 
263
288
  def keys(self) -> list[str]:
289
+ """Get a list of all configuration keys."""
264
290
  return list(self.__keys.values())
265
291
 
266
- def pop(self, key:str) -> Any:
292
+ def pop(self, key: str) -> Any:
293
+ """Delete a specific configuration key."""
267
294
  value = self[key]
268
295
  del self[key]
269
296
  return value
270
297
 
271
- def set(self, key:str, value:Any) -> None:
298
+ def set(self, key: str, value: Any) -> None:
272
299
  """
273
- Sets the configuration data for the specified `key`.
300
+ Set the configuration value for a configuration key.
274
301
 
275
- :param key: The key to associate the configuration data.
276
- :param value: The configuration data so be associated with `key`.
302
+ :param key: The *key* to associate the configuration *value*.
303
+ :param value: The *value* to be associated with the configuration *key*.
277
304
  """
278
305
  if self.__normalize:
279
306
  key = key.upper()
@@ -283,7 +310,8 @@ class Configuration:
283
310
  if o == self:
284
311
  k = self.__keys.get(parts[i].upper())
285
312
  if k is None:
286
- c = Configuration(normalize=self.__normalize, scrubkeys=(None != self.__key_scrub_re))
313
+ c = Configuration(normalize=self.__normalize, scrubkeys=(
314
+ self.__key_scrub_re is None))
287
315
  setattr(o, self.__scrub_key(parts[i]), c)
288
316
  self.__keys[parts[i].upper()] = parts[i]
289
317
  o = c
@@ -291,19 +319,22 @@ class Configuration:
291
319
  o = getattr(self, self.__scrub_key(k))
292
320
  else:
293
321
  if not o.has_key(parts[i]):
294
- c = Configuration(normalize=self.__normalize, scrubkeys=(None != self.__key_scrub_re))
322
+ c = Configuration(normalize=self.__normalize, scrubkeys=(
323
+ self.__key_scrub_re is None))
295
324
  o.set(parts[i], c)
296
325
  o = c
297
326
  else:
298
327
  o = o.get(parts[i])
299
328
  vtype = type(value)
300
329
  if issubclass(vtype, dict):
301
- value = Configuration.fromDictionary(value, normalize=self.__normalize, scrubkeys=self.__key_scrub_re is not None)
330
+ value = Configuration.from_dict(
331
+ value, normalize=self.__normalize, scrubkeys=self.__key_scrub_re is not None)
302
332
  elif issubclass(vtype, list):
303
- l = []
333
+ l: list[Any] = list[Any]()
304
334
  for e in value:
305
335
  if issubclass(type(e), dict):
306
- l.append(Configuration.fromDictionary(e, normalize=self.__normalize, scrubkeys=self.__key_scrub_re is not None))
336
+ l.append(Configuration.from_dict(
337
+ e, normalize=self.__normalize, scrubkeys=self.__key_scrub_re is not None))
307
338
  else:
308
339
  l.append(e)
309
340
  value = l
@@ -318,13 +349,13 @@ class Configuration:
318
349
  else:
319
350
  o.set(key, value)
320
351
 
321
- def toDictionary(self) -> dict[str,Any]:
352
+ def to_dict(self) -> dict[str, Any]:
322
353
  """
323
- Creates a dictionary from the `Configuration` object.
354
+ Create a dictionary from the `Configuration` object.
324
355
 
325
356
  :return: A dictionary containing all keys and their associated values, in a structure that mimics the structure if the data contained within the `Configuration` object.
326
357
  """
327
- result = dict[str,Any]()
358
+ result = dict[str, Any]()
328
359
  for k in self.__keys.values():
329
360
  v = getattr(self, self.__scrub_key(k))
330
361
  if isinstance(v, Configuration):
@@ -341,7 +372,11 @@ class Configuration:
341
372
  result[k] = v
342
373
  return result
343
374
 
375
+ toDictionary = to_dict # noqa: N815
376
+ """⚠️ DEPRECATED: use ``to_dict(...)`` instead."""
377
+
344
378
  def values(self) -> list[Any]:
379
+ """Get a list of all configuration values."""
345
380
  values = []
346
381
  for k in self.__keys.values():
347
382
  v = getattr(self, self.__scrub_key(k))