2015-12-20 12:36:08 +01:00
|
|
|
"""
|
|
|
|
|
Interface to access:
|
|
|
|
|
- local configuration
|
|
|
|
|
- shared configuration
|
|
|
|
|
- shared runtime state
|
|
|
|
|
|
|
|
|
|
All configuration is stored in a single ini-file and
|
|
|
|
|
persistent state is pickle-dumped into a binary file.
|
|
|
|
|
|
|
|
|
|
TODO: check lock safety
|
|
|
|
|
"""
|
|
|
|
|
import json
|
|
|
|
|
import logging
|
2015-12-21 11:21:37 +01:00
|
|
|
import os
|
2015-12-20 12:36:08 +01:00
|
|
|
import sys
|
2015-12-21 11:21:37 +01:00
|
|
|
from fasteners import interprocess_locked
|
2015-12-20 12:36:08 +01:00
|
|
|
from configobj import ConfigObj
|
|
|
|
|
from validate import Validator
|
|
|
|
|
|
2015-12-21 11:21:37 +01:00
|
|
|
|
|
|
|
|
CONFIG_SUFFIX = os.environ.get('BOTSUFFIX', '')
|
2015-12-20 12:36:08 +01:00
|
|
|
__initialized = False
|
2015-12-26 21:24:02 +01:00
|
|
|
__config_store = ConfigObj(
|
|
|
|
|
'local_config{}.ini'.format(CONFIG_SUFFIX),
|
|
|
|
|
configspec='local_config.ini.spec',
|
|
|
|
|
encoding='utf-8'
|
|
|
|
|
)
|
|
|
|
|
runtime_config_store = ConfigObj(
|
|
|
|
|
'persistent_config.ini'.format(CONFIG_SUFFIX),
|
|
|
|
|
configspec='persistent_config.ini.spec',
|
|
|
|
|
encoding='utf-8'
|
|
|
|
|
)
|
2015-12-20 12:36:08 +01:00
|
|
|
|
2015-12-21 16:24:56 +01:00
|
|
|
result = __config_store.validate(Validator())
|
|
|
|
|
# copy is essential to store values with a default.. see configobj.py:2053
|
|
|
|
|
assert runtime_config_store.validate(Validator(), copy=True)
|
2015-12-26 21:24:02 +01:00
|
|
|
# oh look, a bug: https://github.com/DiffSK/configobj/issues/86
|
|
|
|
|
# workaround: set the encoding after validating
|
|
|
|
|
runtime_config_store.encoding = 'utf-8'
|
2015-12-20 12:36:08 +01:00
|
|
|
|
|
|
|
|
if not result:
|
|
|
|
|
print('Config file validation failed!')
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
else:
|
|
|
|
|
__initialized = True
|
|
|
|
|
__config_store.write()
|
|
|
|
|
|
|
|
|
|
|
2015-12-20 15:24:42 +01:00
|
|
|
def conf_get(key):
|
2015-12-20 12:36:08 +01:00
|
|
|
if not __initialized:
|
|
|
|
|
raise RuntimeError("not __initialized")
|
|
|
|
|
try:
|
|
|
|
|
return __config_store[key]
|
|
|
|
|
except KeyError as e:
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
logger.warn('conf(): unknown key ' + str(key))
|
|
|
|
|
print(json.dumps(__config_store, indent=2))
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
2015-12-20 15:24:42 +01:00
|
|
|
def conf_set(key, val):
|
2015-12-20 12:36:08 +01:00
|
|
|
__config_store[key] = val
|
|
|
|
|
__config_store.write()
|
|
|
|
|
return None
|
2015-12-20 15:24:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def runtimeconf_set(key, value):
|
|
|
|
|
runtime_config_store[key] = value
|
2015-12-21 10:41:58 +01:00
|
|
|
runtimeconf_persist()
|
2015-12-20 15:24:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def runtimeconf_get(key, default=None):
|
|
|
|
|
if key is None:
|
|
|
|
|
return runtime_config_store
|
|
|
|
|
else:
|
|
|
|
|
return runtime_config_store.get(key, default=default)
|
|
|
|
|
|
|
|
|
|
|
2015-12-21 11:21:37 +01:00
|
|
|
@interprocess_locked(runtime_config_store.filename)
|
2015-12-21 10:41:58 +01:00
|
|
|
def runtimeconf_persist():
|
2015-12-21 17:03:38 +01:00
|
|
|
# logging.getLogger(__name__).debug(json.dumps(runtime_config_store, indent=2))
|
2015-12-21 10:41:58 +01:00
|
|
|
runtime_config_store.write()
|
|
|
|
|
|
|
|
|
|
|
2015-12-20 15:24:42 +01:00
|
|
|
def runtimeconf_deepget(key, default=None):
|
2015-12-21 10:46:17 +01:00
|
|
|
"""
|
|
|
|
|
access a nested key with get("plugins.moin.enabled")
|
|
|
|
|
:param key: string of nested properties joined with dots
|
|
|
|
|
:param default: default key if None found
|
|
|
|
|
:return:
|
|
|
|
|
"""
|
2015-12-20 15:24:42 +01:00
|
|
|
if '.' not in key:
|
|
|
|
|
return runtimeconf_get(key, default)
|
|
|
|
|
else:
|
|
|
|
|
path = key.split('.')
|
|
|
|
|
value = runtimeconf_get(path.pop(0))
|
|
|
|
|
for p in path:
|
2015-12-21 10:46:17 +01:00
|
|
|
value = value.get(p, default)
|
2015-12-20 15:24:42 +01:00
|
|
|
if value is None:
|
2015-12-21 10:46:17 +01:00
|
|
|
break
|
2015-12-20 15:24:42 +01:00
|
|
|
return value
|