Passed
Push — master ( fd05b8...265ada )
by torrua
02:26
created

keyboa.keyboards.Keyboa.combine()   A

Complexity

Conditions 4

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 14
nop 2
dl 0
loc 28
ccs 10
cts 10
cp 1
crap 4
rs 9.7
c 0
b 0
f 0
1
# -*- coding:utf-8 -*-
2 1
"""
3
This module contains all the necessary functions for
4
creating complex and functional inline keyboards.
5
"""
6
7
8 1
from typing import Union, Optional, Tuple
9 1
from telebot.types import InlineKeyboardMarkup
10
11 1
from keyboa.base import Base
12 1
from keyboa.button import Button
13 1
from keyboa.constants import (
14
    DEFAULT_ITEMS_IN_LINE,
15
    AUTO_ALIGNMENT_RANGE,
16
)
17
18
19 1
class Keyboa(Base):
20
    """Default Keyboa class"""
21
22 1
    def slice(
23
        self,
24
        slice_: slice = slice(None, None, None),
25
    ) -> InlineKeyboardMarkup:
26
        """
27
        :return:
28
        """
29 1
        self._items_sliced = self.items[slice_]
30
31 1
        keyboard = (
32
            self._generated_keyboa
33
            if self.items_in_row or self.alignment
34
            else self._preformatted_keyboa
35
        )
36 1
        self._items_sliced = None
37 1
        return keyboard
38
39 1
    @property
40 1
    def keyboa(self) -> InlineKeyboardMarkup:
41
        """
42
        :return:
43
        """
44 1
        return self.slice()
45
46 1
    @property
47 1
    def _calculated_items_in_row(self) -> Optional[int]:
48
        """
49
        :return:
50
        """
51
52 1
        items_in_row = None
53
54 1
        for divider in self.alignment_range:
55 1
            if not len(self._items_sliced) % divider:
56 1
                items_in_row = divider
57 1
                break
58
59 1
        return items_in_row
60
61 1
    @property
62 1
    def _verified_items_in_row(self) -> int:
63
        """
64
        :return:
65
        """
66 1
        items_in_row = None
67 1
        if self.alignment:
68 1
            items_in_row = self._calculated_items_in_row
69
70 1
        if not items_in_row:
71 1
            items_in_row = DEFAULT_ITEMS_IN_LINE
72 1
        return items_in_row
73
74 1
    @property
75
    def alignment_range(self):
76
        """
77
        :return:
78
        """
79
80 1
        alignment_range = (
81
            AUTO_ALIGNMENT_RANGE if isinstance(self.alignment, bool) else self.alignment
82
        )
83 1
        return (
84
            reversed(alignment_range)
85
            if self.alignment_reverse_range
86
            else alignment_range
87
        )
88
89 1
    @property
90 1
    def _preformatted_keyboa(self) -> InlineKeyboardMarkup:
91
        """
92
        :return:
93
        """
94 1
        self.verify_preformatted_items()
95 1
        keyboard = InlineKeyboardMarkup()
96 1
        for row in self._items_sliced:
97 1
            buttons = self.convert_items_to_buttons(row)
98 1
            keyboard.row(*buttons)
99 1
        return keyboard
100
101 1
    def verify_preformatted_items(self) -> None:
102
        """
103
        Check that every row in kb is a list
104
        :return:
105
        """
106 1
        for index, item in enumerate(self._items_sliced):
107 1
            if not isinstance(item, list):
108 1
                self._items_sliced[index] = [
109
                    item,
110
                ]
111
112 1
    def convert_items_to_buttons(self, items) -> list:
113
        """
114
        :param items:
115
        :return:
116
        """
117 1
        return [
118
            Button(
119
                button_data=item,
120
                front_marker=self.front_marker,
121
                back_marker=self.back_marker,
122
                copy_text_to_callback=self.copy_text_to_callback,
123
            ).generate()
124
            for item in items
125
        ]
126
127 1
    @property
128 1
    def _generated_keyboa(self) -> InlineKeyboardMarkup:
129
        """
130
        :return:
131
        """
132 1
        keyboard = InlineKeyboardMarkup()
133 1
        items_in_row = self._verified_items_in_row
134 1
        rows_in_keyboard = len(self._items_sliced) // items_in_row
135 1
        buttons = self.convert_items_to_buttons(self._items_sliced)
136
137 1
        for _row in range(rows_in_keyboard):
138 1
            keyboard.row(*[buttons.pop(0) for _button in range(items_in_row)])
139 1
        keyboard.row(*buttons)
140
141 1
        return keyboard
142
143 1
    @staticmethod
144
    def merge_keyboards_data(keyboards):
145
        """
146
        :param keyboards:
147
        :return:
148
        """
149 1
        data = []
150 1
        for keyboard in keyboards:
151 1
            if keyboard is None:
152 1
                continue
153
154 1
            if not isinstance(keyboard, InlineKeyboardMarkup):
155 1
                type_error_message = (
156
                    "Keyboard cannot be %s. Only InlineKeyboardMarkup allowed."
157
                    % type(keyboard)
158
                )
159 1
                raise TypeError(type_error_message)
160 1
            data.extend(keyboard.keyboard)
161 1
        return data
162
163 1
    @classmethod
164 1
    def combine(
165
        cls,
166
        keyboards: Optional[
167
            Union[Tuple[InlineKeyboardMarkup, ...], InlineKeyboardMarkup]
168
        ] = None,
169
    ) -> InlineKeyboardMarkup:
170
        """
171
        This function combines multiple InlineKeyboardMarkup objects into one.
172
173
        :param keyboards: Sequence of InlineKeyboardMarkup objects.
174
            Also could be presented as a standalone InlineKeyboardMarkup.
175
176
        :return: InlineKeyboardMarkup
177
        """
178
179 1
        if keyboards is None:
180 1
            return InlineKeyboardMarkup()
181
182 1
        if isinstance(keyboards, InlineKeyboardMarkup):
183 1
            keyboards = (keyboards,)
184
185 1
        for keyboard in keyboards:
186 1
            cls.is_keyboard_proper_type(keyboard)
187
188 1
        data = cls.merge_keyboards_data(keyboards)
189
190
        return cls(items=data).keyboa
191