Package: pyconfig
This module provides python based configuration that is stored in a singleton
object to ensure consistency across your project.Command LineEtcdCode ExamplesChanges3.2.03.1.13.1.03.0.23.0.13.0.0Older VersionsContributorsCommand LinePyconfig has a command line utility that lets you inspect your project to find
all the configuration keys defined.$ pyconfig -h
usage: pyconfig [-h] [-f F | -m M] [-v] [-l] [-a | -k] [-n] [-s] [-c]

Helper for working with pyconfigs

optional arguments:
  -h, --help          show this help message and exit
  -f F, --filename F  parse an individual file or directory
  -m M, --module M    parse a package or module, recursively looking inside it
  -v, --view-call     show the actual pyconfig call made (default: show namespace)
  -l, --load-configs  query the currently set value for each key found
  -a, --all           show keys which don't have defaults set
  -k, --only-keys     show a list of discovered keys without values
  -n, --natural-sort  sort by filename and line (default: alphabetical by key)
  -s, --source        show source annotations (implies --natural-sort)
  -c, --color         toggle output colors (default: True)Example output$pyconfig--file.humbledb.allow_explicit_request=Truehumbledb.auto_start_request=Truehumbledb.connection_pool=300humbledb.tz_aware=Truehumbledb.use_greenlets=Falsehumbledb.write_concern=1$pyconfig--view-call--file.pyconfig.get('humbledb.allow_explicit_request',True)pyconfig.setting('humbledb.auto_start_request',True)pyconfig.setting('humbledb.connection_pool',300)pyconfig.setting('humbledb.tz_aware',True)pyconfig.setting('humbledb.use_greenlets',False)pyconfig.setting('humbledb.write_concern',1)$pyconfig--source--file.# ./humbledb/mongo.py, line 98humbledb.allow_explicit_request=True# ./humbledb/mongo.py, line 178humbledb.connection_pool=300# ./humbledb/mongo.py, line 181humbledb.auto_start_request=True# ./humbledb/mongo.py, line 185humbledb.use_greenlets=False# ./humbledb/mongo.py, line 188humbledb.tz_aware=True# ./humbledb/mongo.py, line 191humbledb.write_concern=1EtcdVersion added: 3.0.0Pyconfig has read-only support for configurations stored in etcd. The preferred
method for configuring Pyconfig to work with etcd is via ENV variables, since
they must be set as early as possible. It is also possible to use the Python
API to make Pyconfig work with etcd.Pyconfig uses a directory namespace to store its dot notation configuration key
names. By default, that namespace is/config/.At a minimum,PYCONFIG_ETCD_HOSTSmust be set to get Pyconfig to try to
read a configuration from etcd using the default settings.You can set a value withetcdctllike:$# The etcdctl command is provided by etcd and not part of pyconfig$etcdctlset/pyconfig/example/my.setting"from etcd"And configure Pyconfig to connect and use that setting:$exportPYCONFIG_ETCD_PREFIX="/pyconfig/example/"$exportPYCONFIG_ETCD_HOSTS="127.0.0.1:2379"$python>>>importpyconfig>>>pyconfig.get('my.setting')'from etcd'Because of Pyconfig’s singleton nature, only one configuration can be accessed
at a time in this way.Environment variables:PYCONFIG_ETCD_PREFIX- The namespace to prefix settings with (default:'/config/')PYCONFIG_ETCD_HOSTS- A comma separated list of hosts, like10.0.0.1:2379,10.0.0.2:2379PYCONFIG_ETCD_CACERT- CA cert file to use for SSLPYCONFIG_ETCD_CERT- Client cert file to use for SSL client authenticationPYCONFIG_ETCD_KEY- Client private key file to use for SSL client authPYCONFIG_ETCD_WATCH- If this is set to a truthy value (a non-empty
string), then pyconfig will keep the local configuration synchronized with
etcd (Version added: 3.1.0)PYCONFIG_ETCD_PROTOCOL- Set this to force HTTPS connections even if not
using certificates. This should be a string of the formhttpsorhttp.
(Version added: 3.2.0)PYCONFIG_ETCD_AUTH- Set this use Basic Authentication with requests.
This should be a string of the formatusername:password. (Version added:
3.2.0)Inheritance:If you want to create a configuration that inherits from an existing
configuration, Pyconfig will look for a special key, which by default is set toconfig.inherit. If this exists and is set to an etcd namespace, that
configuration will be used as the base for the current config.A typical use case would be a Test environment configuration which is derived
from a Development config. Below is a barebones example of how that might be
set up usingetcdctland Pyconfig.$# Create the development settings$etcdctlset/config/app/dev/my.nameexample$etcdctlset/config/app/dev/my.hostnamelocalhost$etcdctlset/config/app/dev/my.api.keyabcdef0123456789$# Create the test settings$etcdctlset/config/app/test/my.hostnametest.example.com$# Tell it to inherit from the development settings$etcdctlset/config/app/test/config.inherit/config/app/dev/$# Configure Pyconfig to use the test configuration$exportPYCONFIG_ETCD_PREFIX="/config/app/test/"$exportPYCONFIG_ETCD_HOSTS="127.0.0.1:2379"$python>>>importpyconfig>>>pyconfig.get('my.hostname')'test.example.com'>>>pyconfig.get('my.name')'example'Code ExamplesThe most basic usage allows you to get, retrieve and modify values. Pyconfig’s
singleton provides convenient accessor methods for these actions:Version changed: 3.0.0As of version 3.0.0, keys are not case sensitive by default.>>>importpyconfig>>>pyconfig.get('my.setting','default')'default'>>>pyconfig.set('my.setting','new')>>>pyconfig.get('my.setting','default')'new'>>>pyconfig.reload(clear=True)>>>pyconfig.get('my.setting','default')'default'You can also opt-out of default values:>>>importpyconfig>>>pyconfig.get('my.setting',allow_default=False)Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"pyconfig/__init__.py",line275,ingetreturnConfig().get(name,default,allow_default=allow_default)File"pyconfig/__init__.py",line234,ingetreturnself.settings[name]LookupError:Nosetting"my.setting"Pyconfig also provides shortcuts for giving classes property descriptors which
map to the current setting stored in the singleton:>>>importpyconfig>>>classMyClass(object):...my_setting=pyconfig.setting('my.setting','default')...>>>MyClass.my_setting'default'>>>MyClass().my_setting'default'>>>pyconfig.set('my.setting',"Hello World!")>>>MyClass.my_setting'Hello World!'>>>MyClass().my_setting'Hello World!'>>>pyconfig.reload(clear=True)>>>MyClass.my_setting'default'TheSettingclass also supports preventing default values.  When set this way,
all reads on the attribute will prevent the use of defaults:>>>importpyconfig>>>classMyClass(object):...my_setting=pyconfig.setting('my.setting',allow_default=False)...>>>MyClass.my_settingTraceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"pyconfig/__init__.py",line84,in__get__allow_default=self.allow_default)File"pyconfig/__init__.py",line232,ingetraiseLookupError('No setting "{}"'.format(name))LookupError:Nosetting"my.setting">>>pyconfig.set('my.setting','new_value')>>>MyClass.my_setting'value'Pyconfig allows you to override settings via a python configuration file, that
defines its configuration keys as a module namespace. By default, Pyconfig will
look on yourPYTHONPATHfor a module namedlocalconfig, and if it exists, it
will use this module namespace to update all configuration settings:# __file__ = "$PYTHONPATH/localconfig.py"frompyconfigimportNamespace# Namespace objects allow you to use attribute assignment to create setting# key namesmy=Namespace()my.setting='from_localconfig'# Namespace objects implicitly return new nested Namespaces when accessing# attributes that don't existmy.nested.setting='also_from_localconfig'With alocalconfigon thePYTHONPATH, it will be loaded before any settings
are read:>>>importpyconfig>>>pyconfig.get('my.setting')'from_localconfig'>>>pyconfig.get('my.nested.setting')'also_from_localconfig'Pyconfig also allows you to create distutils plugins that are automatically
loaded. An examplesetup.py:# __file__ = setup.pyfromsetuptoolsimportsetupsetup(name='pytest',version='0.1.0-dev',py_modules=['myconfig','anyconfig'],entry_points={# The "my" in "my =" indicates a base namespace to use for# the contained configuration. If you do not wish a base# namespace, use "any"'pyconfig':['my = myconfig','any = anyconfig',],},)An example distutils plugin configuration file:# __file__ = myconfig.pyfrompyconfigimportNamespacedefsome_callable():print"This callable was called."print"You can execute any arbitrary code."setting='from_plugin'nested=Namespace()nested.setting='also_from_plugin'Another example configuration file, without a base namespace:# __file__ = anyconfig.pyfrompyconfigimportNamespaceother=Namespace()other.setting='anyconfig_value'Showing the plugin-specified settings:>>>importpyconfig>>>pyconfig.get('my.setting','default')Thiscallablewascalled.Youcanexecuteanyarbitrarycode.'from_plugin'>>>pyconfig.get('my.nested.setting','default')'also_from_plugin'>>>pyconfig.get('other.setting','default')'anyconfig_value'More fancy stuff:>>># Reloading changes re-calls functions...>>>pyconfig.reload()Thiscallablewascalled.Youcanexecuteanyarbitrarycode.>>># This can be used to inject arbitrary code by changing a>>># localconfig.py or plugin and reloading a config... especially>>># when pyconfig.reload() is attached to a signal>>>importsignal>>>signal.signal(signal.SIGUSR1,pyconfig.reload)Pyconfig provides a@reload_hookdecorator that allows you to register
functions or methods to be called when the configuration is reloaded:>>>importpyconfig>>>@pyconfig.reload_hook...defreload():...print"Do something here."...>>>pyconfig.reload()Dosomethinghere.Warning: It should not be used to register large numbers of functions (e.g.
registering a bound method in a class’s__init__method), since there is no
way to un-register a hook and it will cause a memory leak, since a bound method
maintains a strong reference to the bound instance.Note: Because the reload hooks are called without arguments, it will not
work with unbound methods or classmethods.ChangesThis section contains descriptions of changes in each new version.3.2.0AddsPYCONFIG_ETCD_PROTOCOLandPYCONFIG_ETCD_AUTH.Released August 17, 2017.3.1.1Documentation fixes that makes rendering work on PyPI and GitHub again.Released June 16, 2016.3.1.0Adds the ability to watch etcd for changes to values. This can be enabled by
setting the environment variablePYCONFIG_ETCD_WATCH=true.Released June 3, 2016.3.0.2Fixes an issue when using Python 3 compatibility in Python 2.7 and PyOpenSSL.Released September 28, 2015.3.0.1Changes the default inherit depth to 2, which is more useful than 1.3.0.0Adds support for loading configurations from etcd, with inheritance.Usepytool.lang.Namespaceinstead of alternate implementation.Drops support for Python 2.6 and 3.2.Pyconfig setting keys are now case insensitive by default (Usepyconfig.set('pyconfig.case_sensitive',True)to change the behavior)Adds newclear()method for wiping out the cached configuration.Older Versions2.2.1The command line tool will now attempt to handle source files which specify a
non-ascii encoding gracefully.2.2.0Addallow_defaultkeyword option toget()andsetting(). Thanks
toyarbelk!2.1.5Fix regression wherelocalconfig.pywasn’t being loaded on Python 2.7 due
to a logic flow error. Whoops!2.1.4Broke Python 2.6 in 2.1.1, fixed again.2.1.2-2.1.3Package clean up and fixing README to work on PyPI again.2.1.1Fix bug that would break on Python 2.6 and 2.7 when using a localconfig.py.2.1.0Pyconfig now works on Python 3, thanks tohfalcic!2.0.0Pyconfig now has the ability to show you what config keys are defined in a
directory.1.2.0No longer uses Python 2.7format(). Should work on 2.6 and maybe earlier.1.1.2Move version string intopyconfig.__version__1.1.1Fix bug with setup.py that prevented installation1.1.0Allow for implicitly nesting Namespaces when accessing attributes that are
undefinedContributorsshakefu- Creator and maintainerhfalcic- Python 3 compatabilityyarbelk-allow_defaultoption