Package: configuror
configurorYour configuration management toolkit!Why?While usingFlask, I realized that their Config class could be useful for any type
of project. And the utility became more and more obvious to me when I looked at a project likeAnsible. If you look thesectionwhere they define variable precedence, you will notice that there may be several locations for the configuration files,
and these configuration files can be written in different formats (json, yaml..).What if there was a simple tool that would aggregate information from different sources in the order you wanted? This
iswhythe configuror project exists!Installationpipinstallconfigurorconfiguror works starting frompython 3.7. It has a few dependencies:pyyaml>= 5.1tomlDocumentationThe documentation is available athttps://configuror.readthedocs.io/en/latest/.UsageThe main class provided by configuror isConfig. It is an extension of a regular dict object. There are two main ways
to initialize it.Using mapping filesfromconfigurorimportConfigmapping_files={'ini':['foo.ini','bar.ini'],'toml':['foo.toml','bar.toml'],'python':['/path/to/python/file']}config=Config(mapping_files=mapping_files,ignore_file_absence=True)You can define a mapping offile_type: <files>where thefile_typeis the type of configuration file and<files>is the list of files from the lowest to the highest priority where values will be loaded.Since dictionaries are sorted starting from python3.6, the order of the keys is important as it will become the order of
importance of your files. For example in the example above, configuror will load values from files in the following order:foo.inibar.inifoo.tomlbar.toml/path/to/python/fileFor python files, onlyuppercasevariables will be loaded.You will notice the keyword argumentignore_file_absenceinConfigclass initialization. If it is set toTrue, all
files that does not exist will not raisedFileNotFoundError. It comes in handy when you want to retrieve variables
from filesthat may or may not potentially exist. By default this parameter is set toFalse.File extension is not necessary when you use mapping files since the key is already telling which files we work with.
This is not the case with the second way to initializeConfigclass.Using a list of filesfromconfigurorimportConfigfiles=['foo.yml','bar.toml','foobar.json','/path/to/python/file''.env']config=Config(files=files)In this second form of initialization, you pass a list of files you want to retrieve values from the lowest to the
highest priority. File extension ismandatoryhere to help configuror to load the files properly.To know file extensions supported by configuror, you can use the variableEXTENSIONS. it is a mappingfile_type: <extensions>wherefile_typeis a type of file supported likeyamlandextensionsis a list of
recognized extensions for this type of file, e.g:[yml, yaml]Today the file types supported aretoml,yaml,dotenv,ini,pythonandjson.Other usagesSinceConfigobject is a dict-like object, you can pass arbitrary keyword arguments to initialize default values.fromconfigurorimportConfigconfig=Config(FOO=2,BAR='a')print(config)# will print {'FOO': 2, 'BAR': 'a'}You can combine keyword arguments, mapping files and list of files at initialization. The order in which values will be
initialized is the following:values from keyword argumentsvalues from mapping filesvalues from list of filesYou can also add values from files after initialization. There are several practical methods for this:load_from_mapping_files(self, mapping_files: Dict[str, List[str]], ignore_file_absence: bool): It is in fact the
method used under the hood when you initializedConfigobject by passing the parametermapping_files.load_from_files(self, files: List[str], ignore_file_absence: bool): It is the method used under the hood when you
initializedConfigobjects by passing the parameterfiles.load_from_object(self, obj: Union[Object, str]):objcan be an object or a path to a project module
(with dotted notation). Only uppercase attributes of the corresponding object will be retrieved.load_from_python_file(self, filename: str, ignore_file_absence: bool): Loads values from an arbitrary python
file. It would be preferable if it were not a file related to your project (i.e a module). Only uppercase variables
are considered.load_from_json(self, filename: str, ignore_file_absence: bool): Loads values from a json file.load_from_yaml(self, filename: str, ignore_file_absence: bool): Loads values from a yaml file.load_from_toml(self, filenames: Union[str, List[str]], ignore_file_absence: bool): Loads values from a toml file
or a list of toml files.load_from_ini(self, filenames: Union[str, List], ignore_file_absence: bool, interpolation_method: str = 'basic'):
Loads values from an ini file or a list of ini files. There are two interpolation methods that can be used:basicorextendedlike explained in thedocumentation.load_from_dotenv(self, filename: str, ignore_file_absence: bool): Loads values from a dotenv file.Bonus: You also have theupdatemethod of a dict to add/update values.