2015-12-07 02:40:13 +01:00
|
|
|
"""
|
|
|
|
conf.py - PyLink configuration core.
|
|
|
|
|
|
|
|
This module is used to access the complete configuration for the current
|
|
|
|
PyLink instance. It will load the config on first import, taking the
|
|
|
|
configuration file name from the first command-line argument, but defaulting
|
|
|
|
to 'config.yml' if this isn't given.
|
|
|
|
|
|
|
|
If world.testing is set to True, it will return a preset testing configuration
|
|
|
|
instead.
|
|
|
|
|
|
|
|
This module also provides simple checks for validating and loading YAML-format
|
|
|
|
configurations from arbitrary files.
|
|
|
|
"""
|
|
|
|
|
2015-05-31 21:20:09 +02:00
|
|
|
import yaml
|
2015-08-04 04:27:19 +02:00
|
|
|
import sys
|
2015-08-29 04:27:38 +02:00
|
|
|
from collections import defaultdict
|
|
|
|
|
2016-06-21 03:18:54 +02:00
|
|
|
from . import world
|
2015-05-31 21:20:09 +02:00
|
|
|
|
2015-08-29 04:27:38 +02:00
|
|
|
global testconf
|
|
|
|
testconf = {'bot':
|
|
|
|
{
|
|
|
|
'nick': 'PyLink',
|
|
|
|
'user': 'pylink',
|
|
|
|
'realname': 'PyLink Service Client',
|
|
|
|
'serverdesc': 'PyLink unit tests'
|
|
|
|
},
|
2016-03-12 08:03:19 +01:00
|
|
|
'logging':
|
|
|
|
{
|
|
|
|
# Suppress logging in the test output for the most part.
|
|
|
|
'stdout': 'CRITICAL'
|
|
|
|
},
|
2015-08-29 04:27:38 +02:00
|
|
|
'servers':
|
|
|
|
# Wildcard defaultdict! This means that
|
|
|
|
# any network name you try will work and return
|
|
|
|
# this basic template:
|
|
|
|
defaultdict(lambda: {
|
|
|
|
'ip': '0.0.0.0',
|
|
|
|
'port': 7000,
|
|
|
|
'recvpass': "abcd",
|
|
|
|
'sendpass': "chucknorris",
|
|
|
|
'protocol': "null",
|
|
|
|
'hostname': "pylink.unittest",
|
|
|
|
'sid': "9PY",
|
|
|
|
'channels': ["#pylink"],
|
2015-09-13 07:34:55 +02:00
|
|
|
'maxnicklen': 20,
|
|
|
|
'sidrange': '8##'
|
2015-08-29 04:27:38 +02:00
|
|
|
})
|
|
|
|
}
|
2015-09-28 20:30:51 +02:00
|
|
|
|
|
|
|
def validateConf(conf):
|
|
|
|
"""Validates a parsed configuration dict."""
|
|
|
|
assert type(conf) == dict, "Invalid configuration given: should be type dict, not %s." % type(conf).__name__
|
2016-02-08 03:01:12 +01:00
|
|
|
|
|
|
|
for section in ('bot', 'servers', 'login', 'logging'):
|
2015-09-28 20:30:51 +02:00
|
|
|
assert conf.get(section), "Missing %r section in config." % section
|
2016-02-08 03:01:12 +01:00
|
|
|
|
2015-09-28 20:30:51 +02:00
|
|
|
for netname, serverblock in conf['servers'].items():
|
|
|
|
for section in ('ip', 'port', 'recvpass', 'sendpass', 'hostname',
|
2015-09-29 04:22:19 +02:00
|
|
|
'sid', 'sidrange', 'protocol', 'maxnicklen'):
|
2015-09-28 20:30:51 +02:00
|
|
|
assert serverblock.get(section), "Missing %r in server block for %r." % (section, netname)
|
2016-02-08 03:01:12 +01:00
|
|
|
|
2015-09-29 04:22:19 +02:00
|
|
|
assert type(serverblock.get('channels')) == list, "'channels' option in " \
|
2015-09-28 20:30:51 +02:00
|
|
|
"server block for %s must be a list, not %s." % (netname, type(serverblock['channels']).__name__)
|
2016-02-08 03:01:12 +01:00
|
|
|
|
2015-09-28 20:30:51 +02:00
|
|
|
assert type(conf['login'].get('password')) == type(conf['login'].get('user')) == str and \
|
|
|
|
conf['login']['password'] != "changeme", "You have not set the login details correctly!"
|
2016-02-08 03:01:12 +01:00
|
|
|
|
2015-09-28 20:30:51 +02:00
|
|
|
return conf
|
|
|
|
|
2015-11-12 03:55:51 +01:00
|
|
|
def loadConf(fname, errors_fatal=True):
|
2015-09-28 20:30:51 +02:00
|
|
|
"""Loads a PyLink configuration file from the filename given."""
|
|
|
|
with open(fname, 'r') as f:
|
|
|
|
try:
|
|
|
|
conf = yaml.load(f)
|
|
|
|
except Exception as e:
|
|
|
|
print('ERROR: Failed to load config from %r: %s: %s' % (fname, type(e).__name__, e))
|
2015-11-12 03:55:51 +01:00
|
|
|
if errors_fatal:
|
|
|
|
sys.exit(4)
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
return conf
|
2015-09-28 20:30:51 +02:00
|
|
|
|
2015-08-29 23:19:52 +02:00
|
|
|
if world.testing:
|
|
|
|
conf = testconf
|
|
|
|
confname = 'testconf'
|
2015-09-29 04:12:45 +02:00
|
|
|
fname = None
|
2015-08-29 23:19:52 +02:00
|
|
|
else:
|
|
|
|
try:
|
|
|
|
# Get the config name from the command line, falling back to config.yml
|
|
|
|
# if not given.
|
|
|
|
fname = sys.argv[1]
|
|
|
|
confname = fname.split('.', 1)[0]
|
|
|
|
except IndexError:
|
|
|
|
# confname is used for logging and PID writing, so that each
|
|
|
|
# instance uses its own files. fname is the actual name of the file
|
|
|
|
# we load.
|
|
|
|
confname = 'pylink'
|
|
|
|
fname = 'config.yml'
|
2015-09-28 20:30:51 +02:00
|
|
|
conf = validateConf(loadConf(fname))
|