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

keyboa.base.Base.__init__()   A

Complexity

Conditions 1

Size

Total Lines 32
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 24
nop 8
dl 0
loc 32
ccs 16
cts 16
cp 1
crap 1
rs 9.304
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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