Package: birch
Simple hierarchical configuration for Python packages.frombirchimportBirchcfg=Birch('mypackage')# read using a single API both the MYPACKAGE_SERVER_HOSTNAME environment variable# and ~/.mypackage/cfg.json containing {'server': {'port': 55}}connect(cfg['SERVER__HOSTNAME'],cfg['server']['port'])Contents1Installation2Features3Use3.1Basic use3.2The get and mget methods3.3Hierarchical configuration3.4Default values3.5Resolution order3.6Reloading configuration3.7Convenience methods4Configuring birch4.1Configuration directories4.2File formats5Contributing5.1Installing for development5.2Running the tests5.3Adding documentation6Credits1Installationpipinstallbirch2FeaturesSupported formats: JSON, YAML.Pure python.Supports Python 3.6+ (3.5 up to versionv0.0.26).Supported andfully tested on Linux, OS X and Windows.XDG Base Directory Specificationsupport.3Use3.1Basic usebirchprovides an easy way to read simple hierarchical configurations for your Python package or application from both environment variables and configuration files.birchuses namespaces to manage configuration values. The access to each namespace is done via aBirchobject initialized with that namespace. Though written with a specific use case in mind, where a single package uses a single namespace to manage its configuration, any number of namespaces can be used in a single context. For example:frombirchimportBirchzubat_cfg=Birch('zubat')golbat_cfg=Birch('golbat')Each namespace encompasses all values set by either environment variables starting with<uppercase_namespace>_, or defined withincfgfiles (of a supported format) located in a set of pre-configured directories; this set defaults to the~/.config/<namespace>(as par theXDG Base Directory Specification) and the~/.<namespace>directories.For example, thezubatnamespace encompasses environment variables such asZUBAT_HOSTNAMEandZUBAT__PORT, and all mappings in one of the files~/.config/.zubat/cfg.jsonor~/.zubat/cfg.json(if such a file exists).Once defined in such a way, theBirchobject can be used to access the values of mappings of both types (with or without the namespace suffix; casing is also ignored). For example:>>>importos>>>os.environ['ZUBAT_SERVER_HOST']='www.zubat.com'>>>os.environ['ZUBAT_SERVER_PORT']='87'>>>frombirchimportBirch>>>zubat_cfg=Birch('zubat')>>>zubat_cfg['ZUBAT_SERVER_HOST']'www.zubat.com'>>>zubat_cfg['SERVER_PORT']'87'>>>zubat_cfg['server_port']'87'3.2The get and mget methodsBirch objects expose two methods that allow more nuanced retreival of configuration items:Themgetmethod allows the caller to supply acastercallable, through-which any found return value will be passed:>>>os.environ['ZUBAT__PORT']='555'>>>zubat_cfg=Birch('zubat')>>>zubat_cfg.mget('port',int)555Thegetmethod additionally allows you to supply a default value, which is returned if no matching configuration entry is found:>>>importos;os.environ['ZUBAT__PORT']='555'>>>zubat_cfg=Birch('zubat')>>>zubat_cfg.get('port',default=8888,caster=int)555>>>zubat_cfg.get('host',default='defhost')# Default value is returned'defhost'>>>zubat_cfg.get('host')# No error is thrown, None is returnedIf no default value is provided,Noneis returned. To still have aKeyErrorraised in this case usethrow=Truein the function call:>>>importos;os.environ['ZUBAT__PORT']='555'>>>zubat_cfg=Birch('zubat')>>>zubat_cfg.get('host',throw=True)# An error is thrownTraceback(mostrecentcalllast):...KeyError:'zubat: No configuration value for HOST.'To have a warning raised (and the code continue to run) in this case, usewarn=Trueinstead:>>importos;os.environ['ZUBAT__PORT']='555'>>zubat_cfg=Birch('zubat')>>zubat_cfg.get('host',warn=True)# A warning is raisedNoneornovaluewasprovidedtoconfigurationvaluehostforzubat!3.3Hierarchical configurationbirchsupports a simple hierarchy between configuration mappings. Hierarchy is either expressed explicitly in configuration files as nested object/entries (in the case ofjsonandYAMLfiles), or using__(two underscore characters) in the configuration key - both in configuration files and environment variables. Thus, theZUBAT__SERVER__PORTenvironment variable is equivalent to both{'server': {'port': 55}}and{'server__PORT': 55}mappings given in a~/.zubat/cfg.jsonfile, for example. Casing is ignored on all levels.As such, hierarchical mappings can be accessed either using__to indicate a hierarchical path, or using dict-like item access:>>>os.environ['ZUBAT__SERVER__HOST']='www.zubat.com'>>>frombirchimportBirch>>>zubat_cfg=Birch('zubat')>>>zubat_cfg['SERVER__HOST']'www.zubat.com'>>>zubat_cfg['server']['HOST']'www.zubat.com'>>>zubat_cfg['SERVER']['host']'www.zubat.com'Note that this is also true for non-hierarchical configuration file mappings, so{'server__port': 55}, even when given in this form in a configuration file, can be accessed using bothzubat_cfg['SERVER__PORT']andzubat_cfg['SERVER']['PORT'](casing is still ignored on all levels).3.4Default valuesYou can easily assign default values to any number of keys or nested keys by providing thedefaultsconstructor keyword argument with adictcontaining such mappings:>>>frombirchimportBirch>>>defaults={...'server':{'host':'www.boogle.com'},...'server__port':8888,...'GOLBAT__SERVER__PROTOCOL':'http',...}>>>golbat_cfg=Birch('golbat',defaults=defaults)>>>golbat_cfg['SERVER__HOST']'www.boogle.com'>>>golbat_cfg['SERVER']['PORT']8888>>>golbat_cfg['SERVER']['protocol']'http'These values will be overwritten by configuration values loaded from both files and environment variables:>>>os.environ['GOLBAT__SERVER__HOST']='www.zubat.com'>>>golbat_cfg=Birch('golbat',defaults=defaults)>>>golbat_cfg['SERVER__HOST']'www.zubat.com'>>>golbat_cfg['SERVER']['PORT']88883.5Resolution orderA namespace is always loaded with matching environment variablesafterthe configuration file has been loaded, and corresponding mappings will thus override their file-originating counterparts; e.g. theZUBAT__SERVER__PORTenvironment variable will overwrite the value of the mapping{'server': {'port': 55}}given in a~/.zubat/cfg.jsonfile.The lookup order of different files, while deterministic, is undefined and not part of the API. Thus, even with theload_alloption set (see theConfiguring birchsection),cfgfiles with different file extensions can not be relied upon to provide private-vs-shared configuration functionality, or other such configuration modes.Finally, loading of configuration values from both files and environment variables is doneafterthe default values provided in thedefaultsconstructor argument are loaded, so they both override default values.3.6Reloading configurationConfiguration values can be reloaded from all sources - both configuration files and environment variables - by calling thereloadmethod:>>>os.environ['ZUBAT__SERVER__HOST']='www.zubat.com'>>>frombirchimportBirch>>>zubat_cfg=Birch('zubat')>>>zubat_cfg['SERVER__HOST']'www.zubat.com'>>>os.environ['ZUBAT__SERVER__HOST']='New.value!'>>>zubat_cfg.reload()>>>zubat_cfg['server']['HOST']'New.value!'You can set automatic configuration reload on every value inspection by settingauto_reload=Truewhen initializing theBirchobject:>>>os.environ['ZUBAT__SERVER__HOST']='www.zubat.com'>>>frombirchimportBirch>>>zubat_cfg=Birch('zubat',auto_reload=True)>>>zubat_cfg['SERVER__HOST']'www.zubat.com'>>>os.environ['ZUBAT__SERVER__HOST']='New.value!'>>>zubat_cfg['server']['HOST']'New.value!'3.7Convenience methodsThexdg_config_dpath()andxdg_cache_dpath()methods are provided to enable easy access to where the XDG-compliant configuration and cache directories for this namespace should reside.For example, if theXDG_CONFIG_HOMEvariable is set to/Users/daria/myconfig/thenzubat_cfg.xdg_cfg_dpath()will return/Users/daria/myconfig/zubat/, while if it is not set, the same method will return/Users/daria/.config/zubat/.4Configuring birch4.1Configuration directoriesBy defaultbirchlooks for files only in the~/.config/<namespace>and~/.<namespace>directories. You can set a different set of directories to read by populating thedirectoriesconstructor parameter with a different directory path, or a list of paths.Similarly, be defaultbirchreads into the configuration tree only the first compliant file encountered during a lookup in all pre-configured directories; to instead load hierarchical configurations from all such files instead, theload_allconstructor parameter can be set toTrue. Again, load order is undefined, and thus so is the resulting hierarchical configuration.4.2File formatsBy default,birchwill only try to readcfg.jsonfiles. To dictate a different set of supported formats, populate thesupported_formatsconstructor parameter with the desired formats.For example,Birch('zubat',supported_formats=['json','yaml'])will read bothcfg.jsonandcfg.yamlfiles, whileBirch('golbat',supported_formats='yaml')will ony readcfg.yaml(andcfg.yml) files.Currently supported formats are:JSON- Looks forcfg.jsonfiles.YAML- Looks forcfg.yamlandcfg.ymlfiles.5ContributingPackage author and current maintainer is Shay Palachy (shay.palachy@gmail.com); You are more than welcome to approach him for help. Contributions are very welcomed.5.1Installing for developmentClone:gitclonegit@github.com:shaypal5/birch.gitInstall in development mode, including test dependencies:cdbirchpipinstall-e'.[test]'5.2Running the testsTo run the tests use:cdbirchpytest5.3Adding documentationThe project is documented using thenumpy docstring conventions, which were chosen as they are perhaps the most widely-spread conventions that are both supported by common tools such as Sphinx and result in human-readable docstrings. When documenting code you add to this project, followthese conventions.Additionally, if you update thisREADME.rstfile,  usepython setup.py checkdocsto validate it compiles.6CreditsCreated byShay Palachy(shay.palachy@gmail.com).