https://github.com/aphp/confit
Confit is a complete and easy-to-use configuration framework aimed at improving the reproducibility of experiments by relying on the Python type annotations, minimal configuration files and a robust CLI.
https://github.com/aphp/confit
cli configuration interpolation python registry validation
Last synced: 7 months ago
JSON representation
Confit is a complete and easy-to-use configuration framework aimed at improving the reproducibility of experiments by relying on the Python type annotations, minimal configuration files and a robust CLI.
- Host: GitHub
- URL: https://github.com/aphp/confit
- Owner: aphp
- License: bsd-3-clause
- Created: 2023-05-11T13:59:41.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2025-08-26T15:29:58.000Z (10 months ago)
- Last Synced: 2025-09-09T09:23:17.117Z (10 months ago)
- Topics: cli, configuration, interpolation, python, registry, validation
- Language: Python
- Homepage: https://aphp.github.io/confit/
- Size: 2.56 MB
- Stars: 11
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: changelog.md
- Contributing: contributing.md
- License: LICENSE
- Roadmap: roadmap.md
Awesome Lists containing this project
README

[](https://aphp.github.io/confit/latest/)
[](https://pypi.org/project/confit/)
[](https://raw.githubusercontent.com/aphp/confit/coverage/coverage.txt)
# Confit
Confit is a complete and easy-to-use configuration framework aimed at improving the reproducibility
of experiments by relying on the Python typing system, minimal configuration files and
command line interfaces.
## Getting started
Install the library with pip:
```bash
pip install confit
```
Confit only abstracts the boilerplate code related to configuration and
leaves the rest of your code unchanged.
Here is an example:
script.py
```diff
+ from confit import Cli, Registry, RegistryCollection
+ class registry(RegistryCollection):
+ factory = Registry(("test_cli", "factory"), entry_points=True)
+ @registry.factory.register("submodel")
class SubModel:
# Type hinting is optional but recommended !
def __init__(self, value: float, desc: str = ""):
self.value = value
self.desc = desc
+ @registry.factory.register("bigmodel")
class BigModel:
def __init__(self, date: datetime.date, submodel: SubModel):
self.date = date
self.submodel = submodel
+ app = Cli(pretty_exceptions_show_locals=False)
# you can use @confit.validate_arguments instead if you don't plan on using the CLI
+ @app.command(name="script", registry=registry)
def func(modelA: BigModel, modelB: BigModel, seed: int = 42):
assert modelA.submodel is modelB.submodel
print("modelA.date:", modelA.date.strftime("%B %-d, %Y"))
print("modelB.date:", modelB.date.strftime("%B %-d, %Y"))
+ if __name__ == "__main__":
+ app()
```
Create a new config file
The following also works with YAML files
config.cfg
```ini
# CLI sections
[script]
modelA = ${modelA}
modelB = ${modelB}
# CLI common parameters
[modelA]
@factory = "bigmodel"
date = "2003-02-01"
[modelA.submodel]
@factory = "submodel"
value = 12
[modelB]
date = "2003-04-05"
submodel = ${modelA.submodel}
```
and run the following command from the terminal
```bash
python script.py --config config.cfg --seed 43
```
You can still call the `function` method from your code, but now also benefit from
argument validation !
```python
from script import func, BigModel, SubModel
# To seed before creating the models
from confit.utils.random import set_seed
seed = 42
set_seed(seed)
submodel = SubModel(value=12)
func(
# BigModel will cast date strings as datetime.date objects
modelA=BigModel(date="2003-02-01", submodel=submodel),
# Since the modelB argument was typed, the dict is cast as a BigModel instance
modelB=dict(date="2003-04-05", submodel=submodel),
seed=seed,
)
```
```
modelA.date: February 1, 2003
modelB.date: April 5, 2003
```
#### Serialization
You can also serialize registered classes, while keeping references between instances:
```python
from confit import Config
submodel = SubModel(value=12)
modelA = BigModel(date="2003-02-01", submodel=submodel)
modelB = BigModel(date="2003-02-01", submodel=submodel)
print(Config({"modelA": modelA, "modelB": modelB}).to_str())
```
```ini
[modelA]
@factory = "bigmodel"
date = "2003-02-01"
[modelA.submodel]
@factory = "submodel"
value = 12
[modelB]
@factory = "bigmodel"
date = "2003-02-01"
submodel = ${modelA.submodel}
```
#### Error handling
You also benefit from informative validation errors:
```python
func(
modelA=dict(date="hello", submodel=dict(value=3)),
modelB=dict(date="2010-10-05", submodel=dict(value="hi")),
)
```
```
ConfitValidationError: 2 validation errors for __main__.func()
-> modelA.date
invalid date format, got 'hello' (str)
-> modelB.submodel.value
value is not a valid float, got 'hi' (str)
```
Visit the [documentation](https://aphp.github.io/confit/) for more information!
## Acknowledgement
We would like to thank [Assistance Publique – Hôpitaux de Paris](https://www.aphp.fr/)
and [AP-HP Foundation](https://fondationrechercheaphp.fr/) for funding this project.