Failed Conditions
Pull Request — master (#1990)
by Mischa
01:34
created

coalib.misc.StringConverter   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 151
Duplicated Lines 0 %
Metric Value
dl 0
loc 151
rs 8.2857
wmc 39

16 Methods

Rating   Name   Duplication   Size   Complexity  
A StringConverter.__getitem__() 0 2 1
A StringConverter.__str__() 0 2 1
A StringConverter.__get_raw_list() 0 8 2
A StringConverter.__bool__() 0 6 3
A StringConverter.__eq__() 0 2 1
A StringConverter.__len__() 0 2 1
A StringConverter.__iter__() 0 17 2
B StringConverter.__prepare_list() 0 17 7
B StringConverter.__init__() 0 23 4
A StringConverter.keys() 0 2 1
A StringConverter.__int__() 0 2 1
C StringConverter.__prepare_dict() 0 18 8
A StringConverter.value() 0 3 2
A StringConverter.__ne__() 0 2 1
A StringConverter.__float__() 0 2 1
A StringConverter.__url__() 0 12 2
1
import re
2
import validators
3
from collections import Iterable, OrderedDict
4
5
from coalib.misc import Constants
6
from coalib.parsing.StringProcessing import (
7
    unescape, unescaped_split, unescaped_strip)
8
9
10
class StringConverter:
11
    """
12
    Converts strings to other things as needed. If you need some kind of string
13
    conversion that is not implemented here, consider adding it so everyone
14
    gets something out of it.
15
    """
16
17
    def __init__(self,
18
                 value,
19
                 strip_whitespaces=True,
20
                 list_delimiters=None,
21
                 dict_delimiter=":",
22
                 remove_empty_iter_elements=True):
23
        if list_delimiters is None:
24
            list_delimiters = [",", ";"]
25
26
        if not isinstance(list_delimiters, Iterable):
27
            raise TypeError("list_delimiters has to be an Iterable.")
28
        if not isinstance(strip_whitespaces, bool):
29
            raise TypeError("strip_whitespaces has to be a bool parameter")
30
31
        self.__strip_whitespaces = strip_whitespaces
32
        self.__list_delimiters = list_delimiters
33
        self.__dict_delimiter = dict_delimiter
34
        self.__remove_empty_iter_elements = remove_empty_iter_elements
35
36
        self.__escaped_list = None
37
        self.__unescaped_list = None
38
        self.__dict = None
39
        self.value = value
40
41
    def __str__(self):
42
        return unescape(self.value)
43
44
    def __bool__(self):
45
        if str(self).lower() in Constants.TRUE_STRINGS:
46
            return True
47
        if str(self).lower() in Constants.FALSE_STRINGS:
48
            return False
49
        raise ValueError
50
51
    def __len__(self):
52
        return len(str(self))
53
54
    def __int__(self):
55
        return int(str(self))
56
57
    def __float__(self):
58
        return float(str(self))
59
60
    def __url__(self):
61
        """
62
        Determines the url validity of this setting.
63
64
        :return:            url string
65
        :raises ValueError: If the url is not valid.
66
        """
67
        strrep = str(self).strip()
68
        if validators.url(strrep):
69
            return strrep
70
71
        raise ValueError(repr(strrep) + " is not a valid url.")
72
73
    def __iter__(self, remove_backslashes=True):
74
        """
75
        Converts the value to a list using the delimiters given at construction
76
        time.
77
78
        Note that escaped values will be unescaped and escaped list delimiters
79
        will be allowed in values. If you need the escapes you should not
80
        use this routine.
81
82
        :param remove_backslashes: Whether or not to remove the backslashes
83
                                   after conversion.
84
        :return:                   An iterator over all values.
85
        """
86
        if remove_backslashes:
87
            return iter(self.__unescaped_list)
88
        else:
89
            return iter(self.__escaped_list)
90
91
    def __getitem__(self, item):
92
        return self.__dict.__getitem__(item)
93
94
    def keys(self):
95
        return self.__dict.keys()
96
97
    def __get_raw_list(self):
98
        pattern = ("(?:" +
99
                   "|".join(re.escape(v) for v in self.__list_delimiters) +
100
                   ")")
101
102
        return list(unescaped_split(pattern,
103
                                    self.value,
104
                                    use_regex=True))
105
106
    def __prepare_list(self):
107
        self.__escaped_list = self.__get_raw_list()
108
109
        if self.__strip_whitespaces:
110
            self.__escaped_list = [unescaped_strip(elem)
111
                                   for elem in self.__escaped_list]
112
113
        self.__unescaped_list = [unescape(elem)
114
                                 for elem in self.__escaped_list]
115
116
        if self.__remove_empty_iter_elements:
117
            # Need to do after stripping, cant use builtin functionality of
118
            # split.
119
            while "" in self.__unescaped_list:
120
                self.__unescaped_list.remove("")
121
            while "" in self.__escaped_list:
122
                self.__escaped_list.remove("")
123
124
    def __prepare_dict(self):
125
        # We must keep order here, user can drop it later.
126
        self.__dict = OrderedDict()
127
        for elem in self.__get_raw_list():
128
            key_val = unescaped_split(self.__dict_delimiter, elem, max_split=1)
129
130
            if self.__strip_whitespaces:
131
                key_val = [unescaped_strip(item) for item in key_val]
132
133
            key_val = [unescape(item) for item in key_val]
134
135
            if not any(item != "" for item in key_val):
136
                continue
137
138
            if len(key_val) < 2:
139
                self.__dict[key_val[0]] = ""
140
            else:
141
                self.__dict[key_val[0]] = key_val[1]
142
143
    @property
144
    def value(self):
145
        return self.__value
146
147
    @value.setter
148
    def value(self, newval):
149
        self.__value = str(newval)
150
        if self.__strip_whitespaces:
151
            self.__value = unescaped_strip(self.__value)
152
153
        self.__prepare_list()
154
        self.__prepare_dict()
155
156
    def __eq__(self, other):
157
        return isinstance(other, StringConverter) and self.value == other.value
158
159
    def __ne__(self, other):
160
        return not self.__eq__(other)
161