Package: config-io
config_ioconfig_iois a Python package for advanced config reading/parsing/writing.config_iocurrently supportsjsonandyamlformats.InstallingYou can installconfig_ioviapip:pipinstallconfig_ioconfig_ioruns on Python 3, and every build is tested towards Python 3.6, 3.7, 3.8, 3.9, 3.10 on ubuntu, macOS, and windows.UsageFirst, load the library by>>>fromconfig_ioimportConfigConfigis a class for storing configs.Configis similar Python dictionary but with powerful reading/writing/parsing functions.Config readingconfig_iosupports reading configs fromyamlandjsonfiles, as well as from python dictionaries or through keyword arguments.Suppose we have ajsonfileconfig.jsonwith content{"key":"value"}and ayamlfileconfig.yamlwith contentkey:valueBelow are five equivalent ways to create the sameconfigobject:>>>config=Config.load_from_file('config.json')>>>config=Config.load_from_file('config.yaml')>>>config=Config({'key':'value'})>>>config=Config(key='value')>>>config=Config()>>>config.key='value'Theconfigobject is>>>config{'key':'value'}>>>type(config)<class'config_io.config.Config'>Config writingConfig objects (of typeconfig_io.config.Config) can be dumped tojsonandyamlfiles easily by>>>config.dump_to_file('config.json')or>>>config.dump_to_file('config.yaml')Default configIn many use cases, we may want to specify a default config (e.g., default parameters for a program). Other configs (e.g., user-specified parameters) can modify on top of it.config_ioprovides an easy way to do this.Suppose we havedefault.yamlwith contentk1:v1k2:v2k3:v3Now, suppose that we want to specify a config that adds a new keyk4, and changes the value ofk3tonew_v3. We can simply writeconfig.yamlwith contentk4:v4k3:new_v3default:default.yamlconfig_iowill automatically load the config file specified bydefaultas the default parameters:>>>Config.load_from_file('config.yaml'){'k1':'v1','k2':'v2','k3':'new_v3','k4':'v4','default':'default.yaml'}Advanced optionsInstead of specifyingdefault: default.yamlinconfig.yaml, an alternative way is to specify it when loading the config:Config.load_from_file('config.yaml', default='default.yaml').Default configs can be chained in any order. For example,config1.yamlcan setconfig2.yamlas the default config, andconfig2.yamlcan set anotherconfig3.yamlas the default config.Config expansionIn many scenarios, we may want to interact with a set of configs that are created by enumerating all possible combinations of values.config_ioprovides an easy way to do this.For example, assume thatconfig.jsonhas the content:{"k1":[1,2],"k2":[3,4],"k1_expand":true,"k2_expand":true}Loading it would give a list of 4 configs>>>Config.load_from_file('config.json',expand=True)[{'k1':1,'k2':3,'k1_expand':True,'k2_expand':True},{'k1':1,'k2':4,'k1_expand':True,'k2_expand':True},{'k1':2,'k2':3,'k1_expand':True,'k2_expand':True},{'k1':2,'k2':4,'k1_expand':True,'k2_expand':True}]Basically, for the keys such that{KEY_NAME}_expandis set to true,config_iotreats their values as a list of candidate values, and will enumerate all possible combinations of them to generate the list of configs. Note that this feature is turned on only whenexpandis set to true either through the parameter ofload_from_fileor inside the config file.Expansion can also happen after the config is loaded:>>>config=Config({'k1':{'k2':[1,2],'k2_expand':True}})>>>config.expand()[{'k1':{'k2':1,'k2_expand':True}},{'k1':{'k2':2,'k2_expand':True}}]or be applied only for a sub-tree of the config:>>>config.k1.expand()[{'k2':1,'k2_expand':True},{'k2':2,'k2_expand':True}]Advanced optionsThe keys to expand can be on different levels of the config tree. For example, ifconfig.jsonis{"k1":[1,2],"k1_expand":true,"k2":{"k3":[3,4],"k3_expand":true}}Config.load_from_file('config.json', expand=True)would give[{'k1':1,'k1_expand':True,'k2':{'k3':3,'k3_expand':True}},{'k1':1,'k1_expand':True,'k2':{'k3':4,'k3_expand':True}},{'k1':2,'k1_expand':True,'k2':{'k3':3,'k3_expand':True}},{'k1':2,'k1_expand':True,'k2':{'k3':4,'k3_expand':True}}]More on config objectsconfig_io.config.Configis extended from the powerfuladdict library, which supports retrieving config values using either attributes or the standard dictionary item syntax:>>>config=Config(a=1,b={'c':2})>>>config.a1>>>config.b.c2>>>config['b'].c2For more advanced options, please refer toaddict doc.ContributingIf you find bugs/problems or want to add more features to this library, feel free to submit issues or make pull requests.