Package: confit
ConfitConfit 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 startedInstall the library with pip:pipinstallconfitConfit 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 = valueself.desc = desc+ @registry.factory.register("bigmodel")class BigModel:def __init__(self, date: datetime.date, submodel: SubModel):self.date = dateself.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.submodelprint("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 fileconfig.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 terminalpythonscript.py--configconfig.cfg--seed43You can still call thefunctionmethod from your code, but now also benefit from
argument validation !fromscriptimportfunc,BigModel,SubModel# To seed before creating the modelsfromconfit.utils.randomimportset_seedseed=42set_seed(seed)submodel=SubModel(value=12)func(# BigModel will cast date strings as datetime.date objectsmodelA=BigModel(date="2003-02-01",submodel=submodel),# Since the modelB argument was typed, the dict is cast as a BigModel instancemodelB=dict(date="2003-04-05",submodel=submodel),seed=seed,)modelA.date: February 1, 2003
modelB.date: April 5, 2003SerializationYou can also serialize registered classes, while keeping references between instances:fromconfitimportConfigsubmodel=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 handlingYou 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 thedocumentationfor more information!AcknowledgementWe would like to thankAssistance Publique – Hôpitaux de ParisandAP-HP Foundationfor funding this project.