Failed Conditions
Pull Request — master (#1099)
by Mischa
02:03
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_split(self.__dict_delimiter, elem, max_split=1)
115
116
            if self.__strip_whitespaces:
117
                key_val = [unescaped_strip(item) for item in key_val]
118
119
            key_val = [unescape(item) for item in key_val]
120
121
            if not any(item != "" for item in key_val):
122
                continue
123
124
            if len(key_val) < 2:
125
                self.__dict[key_val[0]] = ""
126
            else:
127
                self.__dict[key_val[0]] = key_val[1]
128
129
    @property
130
    def value(self):
131
        return self.__value
132
133
    @value.setter
134
    def value(self, newval):
135
        self.__value = str(newval)
136
        if self.__strip_whitespaces:
137
            self.__value = unescaped_strip(self.__value)
138
139
        self.__prepare_list()
140
        self.__prepare_dict()
141
142
    def __eq__(self, other):
143
        return isinstance(other, StringConverter) and self.value == other.value
144
145
    def __ne__(self, other):
146
        return not self.__eq__(other)
147