configsync-lite 0.1.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.
@@ -0,0 +1,13 @@
1
+ """
2
+ configsync-lite: A lightweight configuration sync utility for Python projects.
3
+ Supports JSON, YAML, and TOML configuration files with environment variable interpolation.
4
+ """
5
+
6
+ __version__ = "0.1.2"
7
+ __author__ = "optimusdemo"
8
+
9
+ from .core import ConfigSync, load_config, merge_configs
10
+ from .validators import validate_schema
11
+ from .env import interpolate_env
12
+
13
+ __all__ = ["ConfigSync", "load_config", "merge_configs", "validate_schema", "interpolate_env"]
@@ -0,0 +1,80 @@
1
+ """
2
+ Core configuration sync functionality.
3
+ """
4
+
5
+ import json
6
+ import os
7
+ from typing import Any, Dict, Optional
8
+
9
+
10
+ class ConfigSync:
11
+ """
12
+ Lightweight configuration manager with environment variable support.
13
+
14
+ Example:
15
+ >>> cfg = ConfigSync("config.json")
16
+ >>> cfg.get("database.host")
17
+ 'localhost'
18
+ """
19
+
20
+ def __init__(self, config_path: str, env_prefix: str = "APP"):
21
+ self.config_path = config_path
22
+ self.env_prefix = env_prefix
23
+ self._config: Dict[str, Any] = {}
24
+ self._load()
25
+
26
+ def _load(self):
27
+ if not os.path.exists(self.config_path):
28
+ return
29
+ with open(self.config_path, "r") as f:
30
+ self._config = json.load(f)
31
+
32
+ def get(self, key: str, default: Any = None) -> Any:
33
+ """Get a config value using dot notation."""
34
+ keys = key.split(".")
35
+ val = self._config
36
+ for k in keys:
37
+ if isinstance(val, dict):
38
+ val = val.get(k)
39
+ else:
40
+ return default
41
+ return val if val is not None else default
42
+
43
+ def set(self, key: str, value: Any):
44
+ """Set a config value using dot notation."""
45
+ keys = key.split(".")
46
+ d = self._config
47
+ for k in keys[:-1]:
48
+ d = d.setdefault(k, {})
49
+ d[keys[-1]] = value
50
+
51
+ def save(self):
52
+ """Persist config to disk."""
53
+ with open(self.config_path, "w") as f:
54
+ json.dump(self._config, f, indent=2)
55
+
56
+ def all(self) -> Dict[str, Any]:
57
+ return self._config
58
+
59
+
60
+ def load_config(path: str) -> Dict[str, Any]:
61
+ """Load a JSON config file and return as dict."""
62
+ with open(path, "r") as f:
63
+ return json.load(f)
64
+
65
+
66
+ def merge_configs(*configs: Dict[str, Any]) -> Dict[str, Any]:
67
+ """Deep merge multiple config dicts. Later values take precedence."""
68
+ result = {}
69
+ for config in configs:
70
+ _deep_merge(result, config)
71
+ return result
72
+
73
+
74
+ def _deep_merge(base: Dict, override: Dict) -> Dict:
75
+ for k, v in override.items():
76
+ if k in base and isinstance(base[k], dict) and isinstance(v, dict):
77
+ _deep_merge(base[k], v)
78
+ else:
79
+ base[k] = v
80
+ return base
configsync_lite/env.py ADDED
@@ -0,0 +1,35 @@
1
+ """
2
+ Environment variable interpolation for config values.
3
+ """
4
+
5
+ import os
6
+ import re
7
+ from typing import Any, Dict
8
+
9
+
10
+ def interpolate_env(config: Dict[str, Any], prefix: str = "") -> Dict[str, Any]:
11
+ """
12
+ Replace ${VAR} placeholders in config values with environment variables.
13
+
14
+ Example:
15
+ >>> os.environ["DB_HOST"] = "localhost"
16
+ >>> interpolate_env({"host": "${DB_HOST}"})
17
+ {'host': 'localhost'}
18
+ """
19
+ result = {}
20
+ for k, v in config.items():
21
+ if isinstance(v, dict):
22
+ result[k] = interpolate_env(v, prefix)
23
+ elif isinstance(v, str):
24
+ result[k] = _replace_vars(v)
25
+ else:
26
+ result[k] = v
27
+ return result
28
+
29
+
30
+ def _replace_vars(value: str) -> str:
31
+ pattern = re.compile(r"\$\{([^}]+)\}")
32
+ def replacer(match):
33
+ var_name = match.group(1)
34
+ return os.environ.get(var_name, match.group(0))
35
+ return pattern.sub(replacer, value)
@@ -0,0 +1,35 @@
1
+ """
2
+ Schema validation for configuration files.
3
+ """
4
+
5
+ from typing import Any, Dict, List, Optional
6
+
7
+
8
+ def validate_schema(config: Dict[str, Any], schema: Dict[str, Any]) -> List[str]:
9
+ """
10
+ Validate a config dict against a simple schema.
11
+ Returns a list of validation errors (empty if valid).
12
+
13
+ Schema format:
14
+ {
15
+ "field_name": {"type": "str", "required": True},
16
+ "port": {"type": "int", "required": False, "default": 8080}
17
+ }
18
+ """
19
+ errors = []
20
+ for field, rules in schema.items():
21
+ value = config.get(field)
22
+ required = rules.get("required", False)
23
+ expected_type = rules.get("type")
24
+
25
+ if value is None:
26
+ if required:
27
+ errors.append(f"Missing required field: '{field}'")
28
+ continue
29
+
30
+ type_map = {"str": str, "int": int, "float": float, "bool": bool, "list": list, "dict": dict}
31
+ if expected_type and expected_type in type_map:
32
+ if not isinstance(value, type_map[expected_type]):
33
+ errors.append(f"Field '{field}' expected {expected_type}, got {type(value).__name__}")
34
+
35
+ return errors
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: configsync-lite
3
+ Version: 0.1.2
4
+ Summary: A lightweight configuration sync utility with environment variable interpolation
5
+ Author-email: optimusdemo <akrine2000@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/akrine2000/configsync-lite
8
+ Project-URL: Repository, https://github.com/akrine2000/configsync-lite
9
+ Project-URL: Issues, https://github.com/akrine2000/configsync-lite/issues
10
+ Keywords: config,configuration,sync,environment,yaml,json
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+
22
+ # configsync-lite
23
+
24
+ A lightweight Python library for managing configuration files with environment variable interpolation and schema validation.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install configsync-lite
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ```python
35
+ from configsync_lite import ConfigSync
36
+
37
+ cfg = ConfigSync("config.json")
38
+ db_host = cfg.get("database.host")
39
+ ```
40
+
41
+ ## Features
42
+
43
+ - JSON configuration file support
44
+ - Dot notation access (`cfg.get("database.host")`)
45
+ - Environment variable interpolation (`${DB_HOST}`)
46
+ - Schema validation
47
+ - Deep merge of multiple configs
48
+ - Zero dependencies
49
+
50
+ ## Usage
51
+
52
+ ### Basic Configuration
53
+
54
+ ```python
55
+ from configsync_lite import ConfigSync, load_config
56
+
57
+ # Load from file
58
+ cfg = ConfigSync("myapp.json")
59
+
60
+ # Get values with dot notation
61
+ host = cfg.get("server.host", default="localhost")
62
+ port = cfg.get("server.port", default=8080)
63
+
64
+ # Set and save
65
+ cfg.set("server.port", 9090)
66
+ cfg.save()
67
+ ```
68
+
69
+ ### Environment Variable Interpolation
70
+
71
+ ```python
72
+ from configsync_lite import load_config, interpolate_env
73
+
74
+ raw = load_config("config.json")
75
+ # config.json contains: {"db": {"password": "${DB_PASSWORD}"}}
76
+
77
+ resolved = interpolate_env(raw)
78
+ # Replaces ${DB_PASSWORD} with actual env var value
79
+ ```
80
+
81
+ ### Merging Configs
82
+
83
+ ```python
84
+ from configsync_lite import merge_configs
85
+
86
+ base = {"server": {"host": "localhost", "port": 8080}}
87
+ override = {"server": {"port": 9090}, "debug": True}
88
+
89
+ merged = merge_configs(base, override)
90
+ # {"server": {"host": "localhost", "port": 9090}, "debug": True}
91
+ ```
92
+
93
+ ### Schema Validation
94
+
95
+ ```python
96
+ from configsync_lite import load_config, validate_schema
97
+
98
+ config = load_config("config.json")
99
+ schema = {
100
+ "host": {"type": "str", "required": True},
101
+ "port": {"type": "int", "required": True},
102
+ "debug": {"type": "bool", "required": False}
103
+ }
104
+
105
+ errors = validate_schema(config, schema)
106
+ if errors:
107
+ print("Config errors:", errors)
108
+ ```
109
+
110
+ ## Contributing
111
+
112
+ See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for development setup and guidelines.
113
+
114
+ ## License
115
+
116
+ MIT
@@ -0,0 +1,8 @@
1
+ configsync_lite/__init__.py,sha256=DLxNWtY0LtNsw1m5zmma-7gIpCo4cFw8qSoNOIkLDT4,455
2
+ configsync_lite/core.py,sha256=6_HCoRUyoQ9hcKUiHU2q9AVxAgLT0pJ9PoIA8s4LH3M,2198
3
+ configsync_lite/env.py,sha256=yr9rkLyBNU757XEnMouxBBlMj86Lw9h_hIuJnNRRPGw,937
4
+ configsync_lite/validators.py,sha256=MP0AwKNo2qB04j4ufe-Mt37v9XtT5zH4i30ADGKoXgc,1149
5
+ configsync_lite-0.1.2.dist-info/METADATA,sha256=Zst0v5CSqVPT8stWJTEcPz99nK9kuRDfNtkUhIhcNto,2937
6
+ configsync_lite-0.1.2.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
7
+ configsync_lite-0.1.2.dist-info/top_level.txt,sha256=uB-kmfkGeh7S0NsZYMS4EQmKAGFaY548GsDy3th8YhA,16
8
+ configsync_lite-0.1.2.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
+ configsync_lite