117 lines
3.1 KiB
Python
Executable File
117 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
For parsing and generating config files.
|
|
"""
|
|
from configparser import ConfigParser
|
|
|
|
class Config():
|
|
def __init__(self, filename):
|
|
"""
|
|
The bot's configuration.
|
|
|
|
The given filename will be associated with the configuration, and is
|
|
the file which will be written if write() is called. If load is not
|
|
given or True, the configuration object will load the attributes from
|
|
the file at filename.
|
|
|
|
A few default values will be set here if they are not defined in the
|
|
config file, or a config file is not loaded. They are documented below.
|
|
"""
|
|
self.filename = filename
|
|
"""The config object's associated file, as noted above."""
|
|
|
|
self.parser = ConfigParser(allow_no_value=True, interpolation=None)
|
|
self.parser.read(self.filename)
|
|
|
|
@property
|
|
def homedir(self):
|
|
"""An alias to config.core.homedir"""
|
|
# Technically it's the other way around, so we can bootstrap filename
|
|
# attributes in the core section, but whatever.
|
|
configured = None
|
|
if self.parser.has_option('core', 'homedir'):
|
|
configured = self.parser.get('core', 'homedir')
|
|
if configured:
|
|
return configured
|
|
else:
|
|
return os.path.dirname(self.filename)
|
|
|
|
def save(self):
|
|
"""Save all changes to the config file."""
|
|
with open(self.filename, 'w') as cfgfile:
|
|
self.parser.write(cfgfile)
|
|
|
|
def add_section(self, name):
|
|
"""
|
|
Add a section to the config file.
|
|
|
|
Returns ``False`` if already exists.
|
|
"""
|
|
try:
|
|
return self.parser.add_section(name)
|
|
except ConfigParser.DuplicateSectionError:
|
|
return False
|
|
|
|
def __getattr__(self, name):
|
|
"""Allows sections to be called like class attributes."""
|
|
if name in self.parser.sections():
|
|
items = self.parser.items(name)
|
|
section = ConfigSection(name, items, self) # Return a section
|
|
setattr(self, name, section)
|
|
return section
|
|
else:
|
|
raise AttributeError("%r object has no attribute %r"
|
|
% (type(self).__name__, name))
|
|
|
|
|
|
class ConfigSection(object):
|
|
"""
|
|
Represents a section of the config file.
|
|
|
|
Contains all keys in thesection as attributes.
|
|
"""
|
|
def __init__(self, name, items, parent):
|
|
object.__setattr__(self, '_name', name)
|
|
object.__setattr__(self, '_parent', parent)
|
|
for item in items:
|
|
value = item[1].strip()
|
|
if not value.lower() == 'none':
|
|
if value.lower() == 'false':
|
|
value = False
|
|
object.__setattr__(self, item[0], value)
|
|
|
|
def __getattr__(self, name):
|
|
return None
|
|
|
|
def __setattr__(self, name, value):
|
|
object.__setattr__(self, name, value)
|
|
if type(value) is list:
|
|
value = ','.join(value)
|
|
self._parent.parser.set(self._name, name, value)
|
|
|
|
def get_list(self, name):
|
|
value = getattr(self, name)
|
|
if not value:
|
|
return []
|
|
if isinstance(value, str):
|
|
value = value.split(',')
|
|
# Keep the split value, so we don't have to keep doing this
|
|
setattr(self, name, value)
|
|
return value
|
|
|
|
|
|
def readConfig(filename):
|
|
"""
|
|
Parses the provided filename and returns the config object.
|
|
"""
|
|
config = ConfigParser(allow_no_value=True, interpolation=None)
|
|
config.read(filename)
|
|
return config
|
|
|
|
|
|
def generateConfig(filename):
|
|
"""
|
|
Generates a blank config file with minimal defaults.
|
|
"""
|
|
pass
|