Platform-aware configuration management (CLI flags + env + YAML/JSON deep-merge)
Reason this release was yanked:
yanking until downstream clients get updated
Project description
Confumo
Confumo derives from "Confuse more". It's a thin Python module that merges command-line flags, environment variables, and YAML/JSON files into a single, deep-merged configuration object. The object is always a singleton per application name and can be exposed at module scope so existing code keeps working.
One line to register your flags, one line to expose the config to the rest of your project.
Highlights
| ✨ | Description |
|---|---|
| Merged sources | argparse • ENV vars • YAML/JSON • defaults |
| Singleton registry | Only one ArgumentParser run per app_name; mismatched config classes raise instead of silently reusing the wrong singleton |
| Auto flag inheritance | Base class + mix-ins + leaf class all show up in --help |
| Lazy “print-once” help | Libraries defer --help; root application prints merged help |
| Module-level proxy | from my_app.config import log_level still works; alias collisions raise unless explicitly replaced |
| Deep-merge | Powered by confuse |
| Cross-platform paths | Uses platformdirs |
Installation
pip install confumo
1 · Define a config class
# ui_layer/config.py
import argparse
from confumo import Confumo
class UIConfig(Confumo):
def add_args(self, p: argparse.ArgumentParser):
p.add_argument('--theme', choices=['light', 'dark', 'auto'], default='auto')
p.add_argument('--font', default='Roboto')
def _init_subclass(self):
self.theme = self.args.theme
self.font = self.cfg['font'].get(str)
def to_dict(self):
return {'theme': self.theme, 'font': self.font}
2 · Expose it (library mode)
UIConfig is meant to be reused by many apps, so the library defers --help
printing:
# ui_layer/config.py (bottom of file)
config = Confumo.expose(
'ui_layer',
UIConfig,
globals(),
root=False,
)
Now any package can do:
from ui_layer import config
print(config.theme)
and the singleton is shared process-wide.
3 · Extend it in an application
# cool_app/config.py
import argparse
from confumo import Confumo
from ui_layer.config import UIConfig
class CoolAppConfig(UIConfig):
def add_args(self, p: argparse.ArgumentParser):
p.add_argument('--log_level', default='INFO',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'])
p.add_argument('--library_path', default='~/Pictures')
def _init_subclass(self):
super()._init_subclass()
self.log_level = self.cfg['log_level'].get(str)
self.library_path = self.cfg['library_path'].get(str)
def to_dict(self):
base = super().to_dict()
base.update({'log_level': self.log_level,
'library_path': self.library_path})
return base
config = Confumo.expose(
'cool_app',
CoolAppConfig,
globals(),
)
Running the application:
python cool_app/main.py --help
prints all flags exactly once.
Confumo collects add_args() methods across the config class MRO, so a
subclass does not have to call super().add_args(p) to inherit parent flags.
Calling super().add_args(p) is also safe: exact duplicate inherited argument
registrations are ignored, while real conflicting option definitions still raise
argparse errors.
4 · Access the config
from cool_app import config
print(config.library_path)
from confumo import Confumo
cfg = Confumo.get('cool_app', CoolAppConfig)
Both lines refer to the same singleton.
Safety checks
Confumo keys singleton instances by app_name, but it also validates the
requested concrete config class on registry hits. If Confumo.get('demo', DemoConfig) created the singleton first, a later Confumo.get('demo', OtherConfig) raises ConfumoSingletonTypeError instead of returning a config
object with the wrong shape. Requesting a base class remains valid when the
existing singleton is an instance of that base class.
Confumo.expose(..., publish_to=(...)) also refuses to replace an existing
Confumo-managed module proxy by default. Publish targets that are already
imported are preflighted before the requested config singleton is constructed,
so an unsafe cross-package alias is rejected before the importing package can
run its own config bootstrap. This prevents one package from silently
repointing another package's config, __getattr__, and __dir__ at an
unrelated singleton. Use replace_existing=True only for an intentional
compatibility shim where that replacement has been audited.
Precedence order
- CLI flags (
--foo bar) - Environment variables (
COOL_APP__FOO=bar) - YAML file (
-c settings.yml) or default path - Defaults hard-coded in your subclass
confuse handles deep-merging dicts and lists.
Persist the merged config
path = config.save_yaml() # ~/.config/cool_app/cool_app_config.yaml (Linux)
The file contains the fully merged state for later inspection.
Testing helpers
config.copy() returns a detached clone whose built-in mutable containers and
argparse namespace state do not alias the singleton. Runtime objects that cannot
be copied, such as GUI widgets stored as leaf values, are preserved by reference.
License
This repository ships under 0BSD; see LICENSE.
Licensing / provenance notice
This repository may include AI-generated material and minimal human-authored material. To the extent any portion of this repository is not copyrightable, it is made available without restriction.
No third-party source or license texts are currently bundled in-tree. Any third-party material added later remains subject to its original terms.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file confumo-0.2.0.tar.gz.
File metadata
- Download URL: confumo-0.2.0.tar.gz
- Upload date:
- Size: 20.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de9c425e8a7d12d2c58015fa7afd6b522b85d50fe796f5c4daf5f66e7c8e796e
|
|
| MD5 |
1289bc5b8091153c693dfa1bcb4e3349
|
|
| BLAKE2b-256 |
e1507378261df30768832da1172d8c80d1fea77416cb5787ea58916bf0ffdd37
|
File details
Details for the file confumo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: confumo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f8731ec4a8bf47a11377622791bd49b7da58689321601ab7631a22ff6561c14
|
|
| MD5 |
fb718ca723a1731481a06415b767fb3b
|
|
| BLAKE2b-256 |
c70acacbd46cf7bc64af8e1ddb32bad2c3b1ad75b1b0c628121114404ffaad88
|