Package: xdgconfig
XDGConfigEasy access to~/.config.InstallationUsing pipSimply runpip3 install --upgrade xdgconfig.By default,xdgconfigonly supports JSON as its serializer, but you can install support for
other serializers by specifiying the format in square brackets, i.e.pip3 install xdgconfig[xml].
The following are available:jsonc: JSON, with commentsini: INI filesxml: eXtensible Markup Language filestoml: Tom's Markup language filesyaml: YAML Ain't Markup Language filesFurthermore there is anallrecipe to install support for every markup supported,
and you can combine them by using a+between 2 targets, i.e.pip3 install xdgconfig[xml+toml]From sourceSimply clone this repo and runpython3 setup.py install.FeaturesConfigobjects use a shared single reference.Serializing to many common formats, including JSON, XML, TOML, YAML, and INIdict-like interfaceAutosaving on mutation of theConfigobject.Smart config loading, especially on Unix-based platformslooks in/etc/prog/config, then in~/.config/prog/configSupports setting a config file path in an environment variable namedPROG_CONFIG_PATHAccessing the config using dot notation (config.keyfor instance). See limitations for guidance.UsagefromxdgconfigimportJsonConfig# Instanciate the JsonConfig object# If you'd rather use a different format, there also are config classes# for TOML, YAML, INI (configparser), and XML.# This will save your configuration under `~/.config/PROG/configconfig=JsonConfig('PROG',autosave=True)config['foo']='bar'# Save a value to the config# Access the value later onprint(config['foo'])# It behaves like a collections.defaultdict as wellconfig['oof']['bar']='baz'# Prints {'oof': {'bar': 'baz'}, 'foo': 'bar'}print(config)Adding onto the libraryCustom serializersYou can add custom serializers support by using a Mixin class, as well as
a serializer class which must have adumpsand aloadsmethod, which will
be used to store and load data from the config file. The data is always
represented as a pythondictobject, but you can serialize any data you want
inside of it.Look at the following example for an implementation guide.fromtypingimportAny,DictfromxdgconfigimportConfigclassMySerializer:defdumps(data:Dict[str,Any])->str:return'\n'.join(f'{k}:{v}'fork,vindata.items())defloads(contents:str)->Dict[str,Any]:returndict(s.split(':')forsincontents.split('\n'))classMySerializerMixin:_SERIALIZER=MySerializerclassMyConfig(MySerializerMixin,Config):...Setting default valuesYou can set default values by creating aMixinclass with a_DEFAULTSclass attribute, such as :frompathlibimportPathfrompprintimportpprintfromxdgconfigimportJsonConfigclassDefaultConfig:_DEFAULTS={'logger.level':'info','logger.verbosity':3,'app.path':str(Path.cwd()),'app.credentials.username':'user','app.credentials.password':'password',}classConfig(DefaultConfig,JsonConfig):...config=Config('PROG','config.json')pprint(config)# Prints the following dict :# {#     'logger': {#         'level': 'info',#         'verbosity': 3#     },#     'app': {#         'path': '$CWD',#         'credentials': {#             'username': 'user',#             'password': 'password'#         }#     }# }Known limitationsUsing anIniConfigobject prevents you from using periods (.) in key names, as they are separators for subdicts.Methods and attributes of theConfigobject all start with a leading underscore (_), hence, using key names with the same convention is discouraged, as it could break the object due to the way dot (.) accessing works. The only exception is thesavemethod, which doesn't start with a leading underscore.There can only be one document per config file, and a config file is a dictionary.Depending on the serializer used, some data types may or may not be available. You can circumvent that by using custom serializers.Configuration files with comments will have their comments dropped when the configuration is saved.