Smart configuration framework
Project description
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:
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
+ 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
# 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
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 !
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:
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())
[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:
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 for more information!
Acknowledgement
We would like to thank Assistance Publique – Hôpitaux de Paris and AP-HP Foundation for funding this project.
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.