Failed Conditions
Pull Request — master (#1099)
by Mischa
02:17
created

coalib.misc.StringConverter.__prepare_list()   B

Complexity

Conditions 7

Size

Total Lines 17

Duplication

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