Metadata-Version: 2.4
Name: confighub
Version: 7.0.1
Summary: Lightweight configuration management with layered sources for Python microservices
Home-page: https://github.com/nvolkov-oss/confighub
Author: Nikita Volkov
Author-email: nvolkov-py@proton.me
License: MIT
Keywords: config configuration management env yaml json toml dotenv layered microservice
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: procwire
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# confighub

Lightweight configuration management with layered sources for Python microservices. Load from JSON, YAML, TOML, INI, .env files with deep merging, interpolation, and change watchers.

## Installation

```bash
pip install confighub
```

## Usage

```python
from confighub import ConfigManager, load_env, merge_deep, interpolate

# Layer multiple configuration sources
config = ConfigManager({'app': {'name': 'myservice', 'debug': False}})
config.load('config/defaults.json')
config.load('config/local.yaml')
config.from_env({'APP_PORT': 'app.port', 'DB_URL': 'database.url'})

# Access nested values with dot notation
port = config.get('app.port', 8080)
db_url = config.get('database.url')

# Watch for changes
config.watch(lambda data: print('Config updated!'))
config.set('app.debug', True)

# Load .env files
env_vars = load_env('.env', override=False)

# Deep merge configs
merged = merge_deep(base_config, override_config)

# Variable interpolation
template = {'url': 'https://${HOST:-localhost}:${PORT}'}
resolved = interpolate(template, {'HOST': 'prod.example.com', 'PORT': '443'})
```

## Features

- **Layered loading** â€” JSON, YAML, TOML, INI, .env with priority ordering
- **Deep merge** â€” nested dict merging with override semantics
- **Dot notation** â€” access `config.get('database.pool.size')`
- **Interpolation** â€” `${VAR}` and `${VAR:-default}` with env fallback
- **Change watchers** â€” callback on config mutations
- **Env mapping** â€” map environment variables to config paths
- **Config diffing** â€” detect changes between versions
- **Thread-safe** â€” all operations are lock-protected

## API

### ConfigManager
- `ConfigManager(defaults=None)` â€” create manager with optional defaults
- `.load(source, priority=0)` â€” load dict, file path, or env mapping
- `.get(key, default=None)` â€” get value by dot-notation key
- `.set(key, value)` â€” set value
- `.has(key)` â€” check existence
- `.delete(key)` â€” remove key
- `.all()` â€” get full config dict
- `.keys(prefix=None)` â€” list keys
- `.from_env(mapping)` â€” load from environment variables
- `.watch(callback)` / `.unwatch(callback)`

### Loaders
- `load_json(path)` / `save_json(path, data)`
- `load_env(path='.env', override=False)` / `save_env(path, data)`
- `load_ini(path)` / `load_yaml(path)` / `load_toml(path)`

### Utilities
- `interpolate(value, context)` â€” variable interpolation
- `merge_deep(base, override)` â€” recursive dict merge
- `freeze(obj)` â€” make hashable (for caching)
- `diff(old, new)` â€” compute config changes

## License

MIT
