aboutsummaryrefslogtreecommitdiff
path: root/src/utils/settings.py
blob: 8040c2e8d498d0c0d656ef475f10a491352a8eb8 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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"]
SETTING_FALSE = ["false", "no", "off", "n"]
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)