Python Configuration System
Description
Library to define configurations using python files.
Installation
Recommended installation with pip:
pip install pycs
Usage
-
Define config schema:
project/config.py
from pycs import CL, CN class BaseClass: pass schema = CN() # Basic config node schema.DICT = CN() # Nested config node schema.DICT.FOO = "FOO" # Config leaf with actual value schema.DICT.INT = 1 schema.NAME = CL(None, str, required=True) # Specification of config leaf to be defined with type schema.CLASSES = CN(BaseClass) # Config node with type specification of its config leaves schema.SUBCLASSES = CN(CL(None, BaseClass, subclass=True)) # Config node with subclass specification of its config leaves schema.VAL = CL(1, desc="Interesting description") # Config leaf with description def transform(cfg: CN) -> None: cfg.NAME = cfg.NAME or "__static__" cfg.DICT.FOO = "BAR" def validate(cfg: CN) -> None: assert len(cfg.NAME) > 0 def hook(cfg: CN) -> None: print("Loaded") # Add transform, validation & hooks function # Transforms are run after config is loaded and can change values in config # Can also be run at runtime using .transform() # If you plan to transform multiple times we strongly recommend to make them idempotent schema.add_transform(transform) # Validators are run after transforms and freeze, with them you can verify additional restrictions schema.add_validator(validate) # Hooks are run after validators and can perform additional actions outside of config schema.add_hook(hook) # Validators and hooks should not (and mostly cannot) modify the config
-
If you want to use configuration with default values or make changes in the program you can use
.static_init():from project.config import schema cfg = schema.static_init() # 'Loaded' print(cfg.DICT.FOO) # 'BAR'
-
If you want to store changes more permanently, please create a config file:
my_cfg.py
from pycs import CN from project.config import schema # Use init_cfg() to separate changes from base variable and freeze schema cfg = schema.init_cfg() # Schema changes are not allowed here, only leaves can be altered. cfg.NAME = "Hello World!" cfg.DICT.INT = 2
You can also create another file to inherit from first and add more changes:
my_cfg2.py
from ntc import CN from .my_cfg import cfg # Separate changes from parent, important when inheriting in multiple files cfg = cfg.clone() cfg.DICT.FOO = "BAR"
There are a few restrictions on imports in configs:
- If you are inheriting changes from another config, please import variable as
cfg - No other import should be named
cfg
- If you are inheriting changes from another config, please import variable as
-
Load actual config and use it in the code.
from pycs import CN cfg = CN.load("my_cfg.py") # Access values as attributes assert cfg.NAME == "Hello World!" assert cfg.DICT.FOO == "BAR"
Other features
-
Load config changes/updates from YAML or JSON
my_changes.yaml
DICT: FOO: BAR
my_changes.json
{ "DICT": { "INT": 2 } }
from project.config import schema cfg = schema.load_from_data_file("my_changes.yaml") assert cfg.DICT.FOO == "BAR" cfg = schema.load_from_data_file("my_changes.json") assert cfg.DICT.INT == 2
-
Save loaded config to a file for tracking:
cfg.save("saved.py")
Please note: There are limitations on which configs can be saved. Generally, config schema should be defined at the module-level and then config should be created with one of:
CN.load()schema.static_init()schema.load_from_data_file()schema.load_or_static()
In addition, only basic changes should be applied to config after loading. See
CfgSaveablefor how to permit saving changes with more complex types.
Development
-
Install dev dependencies:
pip install -e ".[dev]" -
For linting and basic fixes ruff is used:
ruff check . --fix -
This repository follows strict formatting style which will be checked by the CI.
-
To test code, use pytest:
pytest . -
This repository follows semantic-release, which means all commit messages have to follow a style. You can use tools like commitizen to write your commits.
-
You can also use pre-commit to help verify that all changes are valid. Multiple hooks are used, so use the following commands to install:
pre-commit install pre-commit install --hook-type commit-msg
Acknowledgements
This library was inspired by yacs.
Release files for pycs 6.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pycs-6.0.0.tar.gz | 31.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pycs-6.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.7 kB
Release files / pycs-6.0.0.tar.gz
| Download URL | pycs-6.0.0.tar.gz |
|---|---|
| Size | 31.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ddd0cdf7a15dfaa94fbc98ab6259d3827f71bba787c1d7fa411e96e710e77f83
|
|
BLAKE2b-256 checksum How to use checksums |
fded05c783c6542e68f799a3582c921ad8c7a183042083dbd8dd737c9adfb328
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.25.1
|
Release files / pycs-6.0.0-py3-none-any.whl
| Download URL | pycs-6.0.0-py3-none-any.whl |
|---|---|
| Size | 16.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef0e04ae5317f1600b2343d1fc04d89df1269e4aeb49ebf20de27b5ee3bbb536
|
|
BLAKE2b-256 checksum How to use checksums |
5103e946a77303396aac58cfb85c3fe7d57c1db3e30f11f4e2d2ffcc8d681a61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.25.1
|