jsonconfig-utils 1.0.3__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.
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.4
2
+ Name: jsonconfig-utils
3
+ Version: 1.0.3
4
+ Summary: Lightweight JSON configuration loader with environment variable interpolation
5
+ Home-page: https://github.com/config-utils/jsonconfig-utils
6
+ Author: Config Utils Contributors
7
+ Author-email: config-utils-py@proton.me
8
+ Keywords: json config configuration env loader
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Requires-Python: >=3.7
15
+ Description-Content-Type: text/markdown
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: keywords
23
+ Dynamic: requires-python
24
+ Dynamic: summary
25
+
26
+
27
+ # jsonconfig-utils
28
+
29
+ Simple JSON config loader with env var interpolation, schema validation, and nested key access.
30
+
31
+ ## Installation
32
+ ```
33
+ pip install jsonconfig-utils
34
+ ```
35
+
36
+ ## Quick Start
37
+ ```python
38
+ from jsonconfig_utils import load_config
39
+ config = load_config("config.json")
40
+ print(config.database.host)
41
+ ```
@@ -0,0 +1,5 @@
1
+ jsonconfig_utils.py,sha256=aEIS-OmU9ys-OGWWQb28h_tzwSrwqlnAMRTylK3qtX4,2008
2
+ jsonconfig_utils-1.0.3.dist-info/METADATA,sha256=JlOMJ4kBszkQkRk8gG3LjmKKqj7ZHCpOQ2mi6mHjb_8,1144
3
+ jsonconfig_utils-1.0.3.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
4
+ jsonconfig_utils-1.0.3.dist-info/top_level.txt,sha256=Ugw0U-2soo52K13Cz09vLOkjSgCrXKxTgit7v5cVPPs,17
5
+ jsonconfig_utils-1.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ jsonconfig_utils
jsonconfig_utils.py ADDED
@@ -0,0 +1,61 @@
1
+ """jsonconfig-utils: Lightweight JSON configuration loader."""
2
+
3
+ __version__ = "1.0.3"
4
+ __all__ = ["load_config", "ConfigDict", "validate_schema"]
5
+
6
+ import json, os, re
7
+
8
+ def load_config(path, env_interpolate=True, defaults=None):
9
+ with open(path) as f:
10
+ data = json.load(f)
11
+ if defaults:
12
+ data = _merge(defaults, data)
13
+ if env_interpolate:
14
+ data = _interpolate_env(data)
15
+ return ConfigDict(data)
16
+
17
+ def validate_schema(data, schema):
18
+ errors = []
19
+ for key, expected_type in schema.items():
20
+ if key not in data:
21
+ errors.append(f"Missing required key: {key}")
22
+ elif not isinstance(data[key], expected_type):
23
+ errors.append(f"Key \'{key}\' expected {expected_type.__name__}, got {type(data[key]).__name__}")
24
+ return errors
25
+
26
+ class ConfigDict(dict):
27
+ def __getattr__(self, key):
28
+ try:
29
+ val = self[key]
30
+ return ConfigDict(val) if isinstance(val, dict) else val
31
+ except KeyError:
32
+ raise AttributeError(f"Config has no key \'{key}\'")
33
+ def __setattr__(self, key, value):
34
+ self[key] = value
35
+ def get_nested(self, dotted_key, default=None):
36
+ keys = dotted_key.split(".")
37
+ val = self
38
+ for k in keys:
39
+ if isinstance(val, dict) and k in val:
40
+ val = val[k]
41
+ else:
42
+ return default
43
+ return val
44
+
45
+ def _interpolate_env(obj):
46
+ if isinstance(obj, str):
47
+ return re.sub(r"\$\{(\w+)\}", lambda m: os.environ.get(m.group(1), m.group(0)), obj)
48
+ elif isinstance(obj, dict):
49
+ return {k: _interpolate_env(v) for k, v in obj.items()}
50
+ elif isinstance(obj, list):
51
+ return [_interpolate_env(v) for v in obj]
52
+ return obj
53
+
54
+ def _merge(base, override):
55
+ result = base.copy()
56
+ for k, v in override.items():
57
+ if k in result and isinstance(result[k], dict) and isinstance(v, dict):
58
+ result[k] = _merge(result[k], v)
59
+ else:
60
+ result[k] = v
61
+ return result