This repository has been archived on 2025-06-04. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
fl0w-old/Shared/Config.py
2016-03-21 00:15:27 +01:00

118 lines
No EOL
3.2 KiB
Python

from imp import load_source
from os.path import isfile
from marshal import dumps, loads
from types import FunctionType
class OptionDuplicateError(IndexError):
def __init__(self, name):
super(IndexError, self).__init__("'%s' already exists" % name)
class OptionNotFoundError(IndexError):
def __init__(self, name):
super(IndexError, self).__init__("'%s' does not exist" % name)
class NameMustBeStringError(Exception):
def __init__(self):
super(Exception, self).__init__("option names have to be strings")
def make_value(value):
if type(value) is str:
value = '"%s"' % value
elif type(value) in (list, tuple, dict):
value = str(value)
elif type(value) is FunctionType:
value = dumps(value.__code__)
return value
class Option:
def __init__(self, name, default_value, validator=None, comment=""):
if not type(name) is str:
raise NameMustBeStringError()
self.name = name
self.default_value = default_value
self.validator = validator
self.comment = comment
class Config:
def __init__(self, options=[], validation_failed=None, override_on_error=False):
if type(options) in (list, tuple):
for option in options:
if not type(option) is Option:
raise TypeError("all options must be of type Option")
else:
raise TypeError("options must be a list or tuple containing options of type Option")
self.options = options
self.validation_failed = validation_failed
self.override_on_error = override_on_error
def read_from_file(self, file):
if isfile(file):
config = load_source("config", file)
error = False
for option in self.options:
# Make sure all options are avaliable
if option.name not in dir(config):
setattr(config, option.name, option.default_value)
error = True
else:
# Make sure all validators pass
if option.validator != None:
value = getattr(config, option.name)
if not option.validator(value):
setattr(config, option.name, option.default_value)
if self.validation_failed != None:
self.validation_failed(option.name, value)
error = True
if self.override_on_error:
if error:
self.write_to_file(file)
return config
else:
raise FileNotFoundError()
def add(self, new_option):
if type(new_option) is Option:
for option in self.options:
if new_option.name == option.name:
raise OptionDuplicateError(option.name)
self.options.append(new_option)
else:
raise TypeError("invalid type supplied")
def remove(self, option):
if option in self.options:
del self.options[self.options.index(option)]
else:
raise OptionNotFoundError(option.name)
def write_to_file(self, file):
open(file, "w").write(self.get())
def get(self):
contains_function = False
out = ""
for option in self.options:
value = make_value(option.default_value)
if type(option.default_value) is FunctionType:
if not contains_function:
out = "from marshal import loads; from types import FunctionType\n\n" + out
contains_function = True
value = 'FunctionType(loads(%s), globals(), "%s")' % (value, option.name)
out += "%s = %s%s\n" % (option.name, value,
(" # %s" % option.comment) if option.comment else "")
return out
def __repr__(self):
return self.get()