memegen.domain.text.Text.__getitem__()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
class Text:
2
3
    EMPTY = '_'
4
    SPACE = '_'
5
    ALTERNATE_SPACES = ['_', '-']
6
    SPECIAL_CHARACTERS = {
7
        '?': '~q',
8
        '%': '~p',
9
        '#': '~h',
10
        '/': '~s',
11
        '"': "''",
12
    }
13
14
    def __init__(self, path=None, *, translate_spaces=True):
15
        if path is None:
16
            self._parts = []
17
        elif isinstance(path, str):
18
            self._parts = path.split('/')
19
        else:
20
            assert isinstance(path, list)
21
            self._parts = path
22
        self._translate_spaces = translate_spaces
23
24
    def __str__(self):
25
        return ' / '.join(self.lines)
26
27
    def __bool__(self):
28
        return bool(self.path.strip(self.SPACE + '/'))
29
30
    def __getitem__(self, key):
31
        try:
32
            part = self._parts[key]
33
        except (IndexError, ValueError):
34
            return ""
35
        else:
36
            return part.strip()
37
38
    @property
39
    def top(self):
40
        return self.get_line(0)
41
42
    @property
43
    def bottom(self):
44
        return self.get_line(1)
45
46
    @property
47
    def lines(self):
48
        lines = []
49
50
        previous_part = True
51
        for part in self:
52
            if part:
53
                line = self._format_line(part, self._translate_spaces)
54
                lines.append(line)
55
            elif not previous_part:
56
                break
57
            else:
58
                lines.append(' ')
59
            previous_part = part
60
61
        return lines[:-1]
62
63
    @property
64
    def path(self):
65
        paths = []
66
67
        for line in self.lines:
68
            path = self._format_path(line)
69
            paths.append(path)
70
71
        return '/'.join(paths)
72
73
    @classmethod
74
    def _format_line(cls, text, translate_spaces):
75
        for special, replacement in cls.SPECIAL_CHARACTERS.items():
76
            text = text.replace(replacement, special)
77
            text = text.replace(replacement.upper(), special)
78
79
        chars = []
80
        escape = None
81
82
        for index, char in enumerate(text):
83
84
            if char in cls.ALTERNATE_SPACES and translate_spaces:
85
                if char == escape:
86
                    chars[-1] = escape
87
                    escape = None
88
                else:
89
                    chars.append(' ')
90
                    escape = char
91
                continue
92
93
            escape = None
94
95
            if not char.isalpha():
96
                chars.append(char)
97
                continue
98
99
            if len(chars) >= 2:
100
                if char.isupper() and chars[-1].islower() and chars[-2] != ' ':
101
                    chars.append(' ' + char)
102
                    continue
103
104
            if len(chars) >= 1 and len(text) > index + 1:
105
                n_char = text[index + 1]
106
                if char.isupper() and chars[-1].isupper() and n_char.islower():
107
                    chars.append(' ' + char)
108
                    continue
109
110
            chars.append(char)
111
112
        return ''.join(chars).upper()
113
114
    @classmethod
115
    def _format_path(cls, line):
116
        if line == ' ':
117
            path = cls.EMPTY
118
        else:
119
            path = line.lower()
120
            for space in cls.ALTERNATE_SPACES:
121
                path = path.replace(space, space * 2)
122
            path = path.replace(' ', cls.SPACE)
123
            for special, replacement in cls.SPECIAL_CHARACTERS.items():
124
                path = path.replace(special, replacement)
125
126
        return path
127
128
    def get_line(self, index):
129
        return self._format_line(self[index], self._translate_spaces)
130