110 lines
3.4 KiB
Python
110 lines
3.4 KiB
Python
import typing
|
|
|
|
class SettingParseException(Exception):
|
|
pass
|
|
|
|
class Setting(object):
|
|
example: typing.Optional[str] = None
|
|
def __init__(self, name: str, help: str=None, example: str=None):
|
|
self.name = name
|
|
self.help = help
|
|
if not example == None:
|
|
self.example = example
|
|
def parse(self, value: str) -> typing.Any:
|
|
return value
|
|
|
|
def get_example(self):
|
|
if not self.example == None:
|
|
return "Example: %s" % self.example
|
|
else:
|
|
return self._format_example()
|
|
def _format_example(self):
|
|
return None
|
|
|
|
def format(self, value: typing.Any):
|
|
return repr(value)
|
|
|
|
SETTING_TRUE = ["true", "yes", "on", "y", "1"]
|
|
SETTING_FALSE = ["false", "no", "off", "n", "0"]
|
|
class BoolSetting(Setting):
|
|
example: typing.Optional[str] = "on"
|
|
def parse(self, value: str) -> typing.Any:
|
|
value_lower = value.lower()
|
|
if value_lower in SETTING_TRUE:
|
|
return True
|
|
elif value_lower in SETTING_FALSE:
|
|
return False
|
|
return None
|
|
|
|
class IntSetting(Setting):
|
|
example: typing.Optional[str] = "10"
|
|
def parse(self, value: str) -> typing.Any:
|
|
if value == "0":
|
|
return 0
|
|
else:
|
|
stripped = value.lstrip("0")
|
|
if stripped.isdigit():
|
|
return int(stripped)
|
|
return None
|
|
|
|
class IntRangeSetting(IntSetting):
|
|
example: typing.Optional[str] = None
|
|
def __init__(self, n_min: int, n_max: int, name: str, help: str=None,
|
|
example: str=None):
|
|
self._n_min = n_min
|
|
self._n_max = n_max
|
|
Setting.__init__(self, name, help, example)
|
|
|
|
def parse(self, value: str) -> typing.Any:
|
|
out = IntSetting.parse(self, value)
|
|
if not out == None and self._n_min <= out <= self._n_max:
|
|
return out
|
|
return None
|
|
|
|
def _format_example(self):
|
|
return "Must be between %d and %d" % (self._n_min, self._n_max)
|
|
|
|
class OptionsSetting(Setting):
|
|
def __init__(self, options: typing.List[str], name: str, help: str=None,
|
|
example: str=None,
|
|
options_factory: typing.Callable[[], typing.List[str]]=None):
|
|
self._options = options
|
|
self._options_factory = options_factory
|
|
Setting.__init__(self, name, help, example)
|
|
|
|
def _get_options(self):
|
|
if not self._options_factory == None:
|
|
return self._options_factory()
|
|
else:
|
|
return self._options
|
|
|
|
def parse(self, value: str) -> typing.Any:
|
|
value_lower = value.lower()
|
|
for option in self._get_options():
|
|
if option.lower() == value_lower:
|
|
return option
|
|
return None
|
|
|
|
def _format_example(self):
|
|
options = self._get_options()
|
|
options_str = ["'%s'" % option for option in options]
|
|
return "Options: %s" % ", ".join(options_str)
|
|
|
|
class FunctionSetting(Setting):
|
|
def __init__(self, func: typing.Callable[[str], bool], name: str,
|
|
help: str=None, example: str=None, format=None):
|
|
self._func = func
|
|
Setting.__init__(self, name, help, example)
|
|
if not format == None:
|
|
self.format = format # type: ignore
|
|
|
|
def parse(self, value: str) -> typing.Any:
|
|
return self._func(value)
|
|
|
|
def sensitive_format(value: typing.Any):
|
|
return "*"*16
|
|
|
|
class SensitiveSetting(Setting):
|
|
def format(self, value: typing.Any):
|
|
return sensitive_format(value)
|
|
|