Passed
Push — master ( 4e2049...a8cf2f )
by torrua
01:41 queued 10s
created

keyboa.base.Check.is_all_items_in_limits()   A

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 13
ccs 6
cts 6
cp 1
rs 9.9
c 0
b 0
f 0
cc 3
nop 1
crap 3
1
# -*- coding:utf-8 -*-
2 1
"""
3
This module contains basic class with initial Keyboa data.
4
"""
5
# pylint: disable = C0116
6
7 1
from typing import Union, Iterable, Optional
8 1
from telebot.types import InlineKeyboardMarkup
9 1
from keyboa.button import Button
10 1
from keyboa.constants import (
11
    BlockItems,
12
    CallbackDataMarker,
13
    MAXIMUM_ITEMS_IN_KEYBOARD,
14
    MINIMUM_ITEMS_IN_LINE,
15
    MAXIMUM_ITEMS_IN_LINE,
16
)
17
18
19 1
class Check:
20
    """
21
    This class contains all checks for Keyboa Base class values
22
    """
23
24 1
    @staticmethod
25 1
    def is_all_items_in_limits(items) -> None:
26 1
        items_in_keyboard = sum(
27
            len(row) if isinstance(row, (list, tuple, set)) else 1 for row in items
28
        )
29 1
        if items_in_keyboard > MAXIMUM_ITEMS_IN_KEYBOARD:
30 1
            value_error_message_keyboard = (
31
                "Telegram Bot API limit exceeded: The keyboard should have "
32
                "from 1 to %s buttons at all. Your total amount is %s."
33
            )
34 1
            raise ValueError(
35
                value_error_message_keyboard
36
                % (MAXIMUM_ITEMS_IN_KEYBOARD, items_in_keyboard)
37
            )
38
39 1
    @classmethod
40 1
    def is_row_in_limits(cls, items) -> None:
41 1
        if all(isinstance(line, list) for line in items):
42 1
            for line in items:
43 1
                cls.is_items_in_row_limits(len(line))
44
45 1
    @staticmethod
46 1
    def is_items_in_row_limits(items_in_row) -> None:
47 1
        if items_in_row is not None and (
48
            MINIMUM_ITEMS_IN_LINE > items_in_row or items_in_row > MAXIMUM_ITEMS_IN_LINE
49
        ):
50 1
            value_error_message_line = (
51
                "Telegram Bot API limit exceeded: "
52
                "The keyboard line should have from 1 to %s buttons. You entered %s."
53
            )
54 1
            raise ValueError(
55
                value_error_message_line % (MAXIMUM_ITEMS_IN_LINE, items_in_row)
56
            )
57
58 1
    @staticmethod
59 1
    def is_alignment_in_limits(auto_alignment) -> None:
60
        """
61
        :param auto_alignment:
62
        :return:
63
        """
64 1
        if (
65
            max(auto_alignment) > MAXIMUM_ITEMS_IN_LINE
66
            or min(auto_alignment) < MINIMUM_ITEMS_IN_LINE
67
        ):
68 1
            value_error_message = (
69
                "The auto_alignment's item values should be between "
70
                "%s and %s. You entered: %s\n"
71
                "You may define it as 'True' to use AUTO_ALIGNMENT_RANGE."
72
                % (MINIMUM_ITEMS_IN_LINE, MAXIMUM_ITEMS_IN_LINE, auto_alignment)
73
            )
74 1
            raise ValueError(value_error_message)
75
76 1
    @staticmethod
77 1
    def is_alignment_iterable(auto_alignment) -> None:
78
        """
79
        :param auto_alignment:
80
        :return:
81
        """
82 1
        if not (
83
            isinstance(auto_alignment, Iterable)
84
            and all(map(lambda s: isinstance(s, int), auto_alignment))
85
        ):
86 1
            type_error_message = (
87
                "The auto_alignment variable has not a proper type. "
88
                "Only Iterable of integers or boolean type allowed.\n"
89
                "You may define it as 'True' to use AUTO_ALIGNMENT_RANGE."
90
            )
91 1
            raise TypeError(type_error_message)
92
93 1
    @staticmethod
94 1
    def is_keyboard_proper_type(keyboard) -> None:
95 1
        if keyboard and not isinstance(keyboard, InlineKeyboardMarkup):
96 1
            type_error_message = (
97
                "Keyboard to which the new items will be added "
98
                "should have InlineKeyboardMarkup type. Now it is a %s" % type(keyboard)
99
            )
100 1
            raise TypeError(type_error_message)
101
102
103 1
class Base(Check):  # pylint: disable = R0902
104
    """
105
    Base initial class for Keyboa
106
    """
107
108 1
    def __init__(  # pylint: disable = R0913
109
        self,
110
        items: BlockItems,
111
        items_in_row: int = None,
112
        front_marker: CallbackDataMarker = str(),
113
        back_marker: CallbackDataMarker = str(),
114
        copy_text_to_callback: Optional[bool] = None,
115
        alignment: Union[bool, Iterable] = None,
116
        alignment_reverse_range: Optional[bool] = None,
117
    ):
118 1
        self._items = None
119 1
        self.items = items
120
121 1
        self._items_in_row = None
122 1
        self.items_in_row = items_in_row
123
124 1
        self._front_marker = str()
125 1
        self.front_marker = front_marker
126
127 1
        self._back_marker = str()
128 1
        self.back_marker = back_marker
129
130 1
        self._copy_text_to_callback = None
131 1
        self.copy_text_to_callback = copy_text_to_callback
132
133 1
        self._alignment = None
134 1
        self.alignment = alignment
135
136 1
        self._alignment_reverse_range = None
137 1
        self.alignment_reverse_range = alignment_reverse_range
138
139 1
        self._items_sliced = None
140
141 1
    @property
142 1
    def items(self) -> BlockItems:
143 1
        return self._items
144
145 1
    @items.setter
146 1
    def items(self, items_value) -> None:
147 1
        if items_value is None or not items_value:
148 1
            raise ValueError("Items should not be None")
149 1
        if not isinstance(items_value, list):
150 1
            items_value = [
151
                items_value,
152
            ]
153
154 1
        self.is_all_items_in_limits(items_value)
155 1
        self.is_row_in_limits(items_value)
156 1
        self._items = items_value
157
158 1
    @property
159 1
    def items_in_row(self) -> int:
160 1
        return self._items_in_row
161
162 1
    @items_in_row.setter
163 1
    def items_in_row(self, items_in_row_value) -> None:
164 1
        self.is_items_in_row_limits(items_in_row_value)
165 1
        self._items_in_row = items_in_row_value
166
167 1
    @property
168 1
    def front_marker(self) -> CallbackDataMarker:
169 1
        return self._front_marker
170
171 1
    @front_marker.setter
172 1
    def front_marker(self, front_marker_value) -> None:
173 1
        Button.get_checked_marker(front_marker_value)
174 1
        self._front_marker = front_marker_value
175
176 1
    @property
177 1
    def back_marker(self) -> CallbackDataMarker:
178 1
        return self._back_marker
179
180 1
    @back_marker.setter
181 1
    def back_marker(self, back_marker_value) -> None:
182 1
        Button.get_checked_marker(back_marker_value)
183 1
        self._back_marker = back_marker_value
184
185 1
    @property
186 1
    def copy_text_to_callback(self) -> bool:
187 1
        return self._copy_text_to_callback
188
189 1
    @copy_text_to_callback.setter
190 1
    def copy_text_to_callback(self, copy_text_to_callback_value) -> None:
191 1
        if not isinstance(copy_text_to_callback_value, (bool, type(None))):
192 1
            raise TypeError(
193
                "'copy_text_to_callback' should have only bool or none type"
194
            )
195 1
        self._copy_text_to_callback = copy_text_to_callback_value
196
197 1
    @property
198 1
    def alignment(self) -> Union[bool, Iterable]:
199
200 1
        return self._alignment
201
202 1
    @alignment.setter
203 1
    def alignment(self, alignment_value) -> None:
204 1
        if alignment_value is None or isinstance(alignment_value, bool):
205 1
            self._alignment = alignment_value
206 1
            return
207 1
        self.is_alignment_iterable(alignment_value)
208 1
        self.is_alignment_in_limits(alignment_value)
209 1
        self._alignment = alignment_value
210
211 1
    @property
212 1
    def alignment_reverse_range(self) -> bool:
213 1
        return self._alignment_reverse_range
214
215 1
    @alignment_reverse_range.setter
216 1
    def alignment_reverse_range(self, alignment_reverse_range_value) -> None:
217
        self._alignment_reverse_range = alignment_reverse_range_value
218