20251005
This commit is contained in:
17
.run/Тест ActionState.run.xml
Normal file
17
.run/Тест ActionState.run.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Тест ActionState" type="tests" factoryName="Autodetect">
|
||||||
|
<module name="anb_python_components" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/tests/classes" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="_new_additionalArguments" value="""" />
|
||||||
|
<option name="_new_target" value=""$PROJECT_DIR$/tests/classes/action_state_test.py"" />
|
||||||
|
<option name="_new_targetType" value=""PATH"" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
17
.run/Тест VersionInfo.run.xml
Normal file
17
.run/Тест VersionInfo.run.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Тест VersionInfo" type="tests" factoryName="Autodetect">
|
||||||
|
<module name="anb_python_components" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/tests/types" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="_new_additionalArguments" value="""" />
|
||||||
|
<option name="_new_target" value=""$PROJECT_DIR$/tests/types/version_info_test.py"" />
|
||||||
|
<option name="_new_targetType" value=""PATH"" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
210
anb_python_components/classes/action_state.py
Normal file
210
anb_python_components/classes/action_state.py
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
# anb_python_components/classes/action_state.py
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from anb_python_components.exceptions.wrong_type_exception import WrongTypeException
|
||||||
|
from anb_python_components.models.action_state_message import ActionStateMessage, MessageType
|
||||||
|
|
||||||
|
class ActionState[T]:
|
||||||
|
"""
|
||||||
|
Класс для хранения состояния действия.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__ (self, default: T | None = None):
|
||||||
|
self.__messages: list[ActionStateMessage] = []
|
||||||
|
self.value: T | None = default
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_string_error_only () -> Callable[[ActionStateMessage], bool]:
|
||||||
|
"""
|
||||||
|
Возвращает лямбду для фильтрации только сообщений типа ERROR.
|
||||||
|
"""
|
||||||
|
return lambda message: message.message_type == MessageType.ERROR
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_string_error_and_warning () -> Callable[[ActionStateMessage], bool]:
|
||||||
|
"""
|
||||||
|
Возвращает лямбду для фильтрации сообщений типа ERROR и WARNING.
|
||||||
|
"""
|
||||||
|
return lambda message: message.message_type in [MessageType.ERROR, MessageType.WARNING]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_string_all () -> Callable[[ActionStateMessage], bool]:
|
||||||
|
"""
|
||||||
|
Возвращает лямбду для фильтрации всех сообщений.
|
||||||
|
"""
|
||||||
|
return lambda message: True
|
||||||
|
|
||||||
|
def add_message (self, message: ActionStateMessage):
|
||||||
|
"""
|
||||||
|
Добавляет сообщение в список.
|
||||||
|
:param message: Сообщение.
|
||||||
|
"""
|
||||||
|
if message:
|
||||||
|
self.__messages.append(message)
|
||||||
|
else:
|
||||||
|
raise ValueError("Сообщение не может быть пустым.")
|
||||||
|
|
||||||
|
def add (self, message_type: MessageType, message: str, flags: dict[str, bool] | None = None):
|
||||||
|
"""
|
||||||
|
Добавляет сообщение в список.
|
||||||
|
:param message_type: Тип сообщения.
|
||||||
|
:param message: Сообщение.
|
||||||
|
:param flags: Флаги (необязательный).
|
||||||
|
"""
|
||||||
|
# Создаём сообщение
|
||||||
|
message = ActionStateMessage(message_type, message, flags)
|
||||||
|
|
||||||
|
# Добавляем в список
|
||||||
|
self.add_message(message)
|
||||||
|
|
||||||
|
def add_info (self, message: str, flags: dict[str, bool] | None = None):
|
||||||
|
"""
|
||||||
|
Добавляет информационное сообщение в список.
|
||||||
|
:param message: Сообщение.
|
||||||
|
:param flags: Флаги (необязательный).
|
||||||
|
"""
|
||||||
|
self.add(MessageType.INFO, message, flags)
|
||||||
|
|
||||||
|
def add_warning (self, message: str, flags: dict[str, bool] | None = None):
|
||||||
|
"""
|
||||||
|
Добавляет предупреждающее сообщение в список.
|
||||||
|
:param message: Сообщение.
|
||||||
|
:param flags: Флаги (необязательный).
|
||||||
|
"""
|
||||||
|
self.add(MessageType.WARNING, message, flags)
|
||||||
|
|
||||||
|
def add_error (self, message: str, flags: dict[str, bool] | None = None):
|
||||||
|
"""
|
||||||
|
Добавляет сообщение об ошибке в список.
|
||||||
|
:param message: Сообщение.
|
||||||
|
:param flags: Флаги (необязательный).
|
||||||
|
"""
|
||||||
|
self.add(MessageType.ERROR, message, flags)
|
||||||
|
|
||||||
|
def add_state (self, state, clear_all_before: bool = False):
|
||||||
|
"""
|
||||||
|
Добавляет другое состояние действия в текущее.
|
||||||
|
:param state:ActionState - Состояние действия.
|
||||||
|
:param clear_all_before - Очистить список перед добавлением (по умолчанию - False).
|
||||||
|
|
||||||
|
ВНИМАНИЕ! Метод не передаёт значение value состояния, а просто переносит его сообщения.
|
||||||
|
"""
|
||||||
|
# Проверяем тип
|
||||||
|
if not isinstance(state, ActionState):
|
||||||
|
# - и если не ActionState, то бросаем исключение
|
||||||
|
raise WrongTypeException("Неверный тип состояния действия.", "ActionState", str(type(state)), "state")
|
||||||
|
|
||||||
|
# Если нужно очистить список перед добавлением
|
||||||
|
if clear_all_before:
|
||||||
|
# - то очищаем его
|
||||||
|
self.__messages.clear()
|
||||||
|
|
||||||
|
# Получаем список сообщений из состояния
|
||||||
|
state_messages = state.get_messages()
|
||||||
|
|
||||||
|
# Перебираем все сообщения переданного состояния
|
||||||
|
for state_message in state_messages:
|
||||||
|
# - и если это сообщение состояния
|
||||||
|
if isinstance(state_message, ActionStateMessage):
|
||||||
|
# -- то добавляем его в текущий список
|
||||||
|
self.__messages.append(state_message)
|
||||||
|
|
||||||
|
def get_messages (self, predicate: Callable[[ActionStateMessage], bool] | None = None) -> list[ActionStateMessage]:
|
||||||
|
"""
|
||||||
|
Возвращает список сообщений с учетом условия (если указан).
|
||||||
|
:param predicate: Условие выборки.
|
||||||
|
:return: Список сообщений.
|
||||||
|
"""
|
||||||
|
# Если условие указано
|
||||||
|
if predicate:
|
||||||
|
# - то фильтруем список по нему
|
||||||
|
return list(filter(predicate, self.__messages))
|
||||||
|
else:
|
||||||
|
# - если нет, то просто возвращаем весь список
|
||||||
|
return self.__messages.copy()
|
||||||
|
|
||||||
|
def get_string_messages (
|
||||||
|
self, predicate: Callable[[ActionStateMessage], bool] | None = None, separator: str = "\n"
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Возвращает строку сообщений с учетом условия (если указано).
|
||||||
|
:param predicate: Условие выборки (необязательный).
|
||||||
|
:param separator: Разделитель строк (необязательный, по умолчанию - "\n").
|
||||||
|
:return: Строка сообщений.
|
||||||
|
"""
|
||||||
|
# Получаем список сообщений с учетом условия
|
||||||
|
messages = self.get_messages(predicate)
|
||||||
|
|
||||||
|
# Объединяем их в строку и возвращаем
|
||||||
|
return separator.join(map(lambda message: message.message, messages))
|
||||||
|
|
||||||
|
def has_infos (self) -> bool:
|
||||||
|
"""
|
||||||
|
Проверяет, есть ли в списке информационные сообщения.
|
||||||
|
:return: True, если есть, иначе False.
|
||||||
|
"""
|
||||||
|
return any(message.message_type == MessageType.INFO for message in self.__messages)
|
||||||
|
|
||||||
|
def has_warnings (self) -> bool:
|
||||||
|
"""
|
||||||
|
Проверяет, есть ли в списке предупреждающие сообщения.
|
||||||
|
:return: True, если есть, иначе False.
|
||||||
|
"""
|
||||||
|
return any(message.message_type == MessageType.WARNING for message in self.__messages)
|
||||||
|
|
||||||
|
def has_errors (self) -> bool:
|
||||||
|
"""
|
||||||
|
Проверяет, есть ли в списке сообщения об ошибках.
|
||||||
|
:return: True, если есть, иначе False.
|
||||||
|
"""
|
||||||
|
return any(message.message_type == MessageType.ERROR for message in self.__messages)
|
||||||
|
|
||||||
|
def is_success (self, ignore_warnings: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Проверяет, успешное ли состояние действия.
|
||||||
|
:param ignore_warnings: Игнорировать предупреждения (по умолчанию - False).
|
||||||
|
:return: Успешно ли состояние действия.
|
||||||
|
"""
|
||||||
|
# Задаем начальное значение результата
|
||||||
|
result = True
|
||||||
|
|
||||||
|
# Если не нужно игнорировать предупреждения
|
||||||
|
if not ignore_warnings:
|
||||||
|
# - то проверяем наличие предупреждений
|
||||||
|
result = result and not self.has_warnings()
|
||||||
|
|
||||||
|
# Проверяем наличие ошибок
|
||||||
|
result = result and not self.has_errors()
|
||||||
|
|
||||||
|
# Выдаём результат
|
||||||
|
return result
|
||||||
|
|
||||||
|
def clear (self, predicate: Callable[[ActionStateMessage], bool] | None = None):
|
||||||
|
"""
|
||||||
|
Очищает список сообщений с учетом условия (если указан).
|
||||||
|
:param predicate: Функция для фильтрации сообщений для очистки.
|
||||||
|
"""
|
||||||
|
# Если условие указано
|
||||||
|
if predicate:
|
||||||
|
# - то фильтруем список
|
||||||
|
self.__messages = list(filter(lambda message: not predicate(message), self.__messages))
|
||||||
|
else:
|
||||||
|
# - если нет, то просто очищаем список
|
||||||
|
self.__messages.clear()
|
||||||
|
|
||||||
|
def count (self, predicate: Callable[[ActionStateMessage], bool] | None = None) -> int:
|
||||||
|
"""
|
||||||
|
Возвращает количество сообщений в списке с учетом условия (если указано).
|
||||||
|
:param predicate: Условие выборки (необязательный).
|
||||||
|
:return: Количество сообщений.
|
||||||
|
"""
|
||||||
|
# Если условие указано
|
||||||
|
if predicate:
|
||||||
|
# - то фильтруем список по нему
|
||||||
|
messages = self.get_messages(predicate)
|
||||||
|
|
||||||
|
# - и возвращаем его длину
|
||||||
|
return len(messages)
|
||||||
|
else:
|
||||||
|
# - если нет, то просто возвращаем длину списка
|
||||||
|
return len(self.__messages)
|
44
anb_python_components/enums/message_type.py
Normal file
44
anb_python_components/enums/message_type.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# anb_python_components/enums/message_type.py
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class MessageType(Enum):
|
||||||
|
"""
|
||||||
|
Перечисление типов сообщений:
|
||||||
|
- SUCCESS: Успешное выполнение.
|
||||||
|
- INFO: Информация.
|
||||||
|
- WARNING: Предупреждение.
|
||||||
|
- ERROR: Ошибка.
|
||||||
|
"""
|
||||||
|
# Успешное выполнение
|
||||||
|
SUCCESS = 0
|
||||||
|
|
||||||
|
# Информация
|
||||||
|
INFO = 1
|
||||||
|
|
||||||
|
# Предупреждение
|
||||||
|
WARNING = 2
|
||||||
|
|
||||||
|
# Ошибка
|
||||||
|
ERROR = 3
|
||||||
|
|
||||||
|
def __str__ (self):
|
||||||
|
"""
|
||||||
|
Переопределение метода __str__.
|
||||||
|
:return: Текстовое представление перечисления.
|
||||||
|
"""
|
||||||
|
# Получаем текстовое представление
|
||||||
|
match self:
|
||||||
|
case MessageType.SUCCESS:
|
||||||
|
result = "Успех"
|
||||||
|
case MessageType.INFO:
|
||||||
|
result = "Информация"
|
||||||
|
case MessageType.WARNING:
|
||||||
|
result = "Предупреждение"
|
||||||
|
case MessageType.ERROR:
|
||||||
|
result = "Ошибка"
|
||||||
|
case _:
|
||||||
|
result = "Неизвестный тип сообщения"
|
||||||
|
|
||||||
|
# Возвращаем результат
|
||||||
|
return result
|
1
anb_python_components/models/__init__.py
Normal file
1
anb_python_components/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# anb_python_components/models/__init__.py
|
27
anb_python_components/models/action_state_message.py
Normal file
27
anb_python_components/models/action_state_message.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# anb_python_components/models/action_state_message.py
|
||||||
|
from anb_python_components.enums.message_type import MessageType
|
||||||
|
|
||||||
|
class ActionStateMessage:
|
||||||
|
"""
|
||||||
|
Модель сообщения о состояния действия.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__ (
|
||||||
|
self, message_type: MessageType = MessageType.INFO, message: str = "", flags: dict[str, bool] | None = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Конструктор.
|
||||||
|
:param message_type: Тип сообщения (по умолчанию, INFO).
|
||||||
|
:param message: Текст сообщения (по умолчанию, пустая строка).
|
||||||
|
:param flags: Флаги сообщения (по умолчанию, пустой словарь).
|
||||||
|
"""
|
||||||
|
self.message_type: MessageType = message_type
|
||||||
|
self.message: str = message
|
||||||
|
self.flags: dict[str, bool] = flags if flags is not None else []
|
||||||
|
|
||||||
|
def __str__ (self):
|
||||||
|
"""
|
||||||
|
Переопределение метода __str__.
|
||||||
|
:return: Текстовое представление модели.
|
||||||
|
"""
|
||||||
|
return f"[{str(self.message_type).upper()}] {self.message}"
|
413
anb_python_components/types/two_dim_size.py
Normal file
413
anb_python_components/types/two_dim_size.py
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
# anb_python_components/types/two_dim_size.py
|
||||||
|
|
||||||
|
class TwoDimSize:
|
||||||
|
"""
|
||||||
|
Класс TwoDimSize для представления размеров двухмерного объекта.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Разделитель частей по умолчанию.
|
||||||
|
DEFAULT_DELIMITER: str = ':'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_valid_num (num: int, min_num: int | None = 0, max_num: int | None = None) -> int:
|
||||||
|
"""
|
||||||
|
Получает корректное значение представленного числа.
|
||||||
|
:param num: Проверяемое значение.
|
||||||
|
:param min_num: Минимальное значение (по умолчанию 0). Если None, то считается, что минимальное значение не ограничено.
|
||||||
|
:param max_num: Максимальное значение (по умолчанию None). Если None, то считается, что максимальное значение не ограничено.
|
||||||
|
:return: Корректное значение.
|
||||||
|
"""
|
||||||
|
# Флаг, разрешающий или запрещающий отрицательные значения
|
||||||
|
is_negative_allowed = min_num < 0 or min_num is None
|
||||||
|
|
||||||
|
# Безлимитные значения
|
||||||
|
# - для минимального значения
|
||||||
|
is_unlimited_min = min_num is None
|
||||||
|
# - для максимального значения
|
||||||
|
is_unlimited_max = max_num is None
|
||||||
|
|
||||||
|
# Если значение отрицательное, а отрицательные значения запрещены
|
||||||
|
if num < 0 and not is_negative_allowed:
|
||||||
|
# - то возвращаю 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Если значение вышло за ограничения минимальное значения
|
||||||
|
if not is_unlimited_min and num < min_num:
|
||||||
|
# - то возвращаю минимальное значение
|
||||||
|
return min_num
|
||||||
|
|
||||||
|
# Если значение вышло за ограничения максимальное значения
|
||||||
|
if not is_unlimited_max and num > max_num:
|
||||||
|
# - то возвращаю максимальное значение
|
||||||
|
return max_num
|
||||||
|
|
||||||
|
# Если значение корректно, то возвращаю его
|
||||||
|
return num
|
||||||
|
|
||||||
|
def __init__ (
|
||||||
|
self, width: int = 0, height: int = 0, min_width: int | None = 0, max_width: int | None = None,
|
||||||
|
min_height: int | None = 0, max_height: int | None = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Инициализирует объект TwoDimSize.
|
||||||
|
:param width: Ширина (по умолчанию 0).
|
||||||
|
:param height: Высота (по умолчанию 0).
|
||||||
|
:param min_width: Минимальная ширина (по умолчанию 0). Если None, то считается, что минимальная ширина не ограничена.
|
||||||
|
:param max_width: Максимальная ширина (по умолчанию None). Если None, то считается, что максимальная ширина не ограничена.
|
||||||
|
:param min_height: Минимальная высота (по умолчанию 0). Если None, то считается, что минимальная высота не ограничена.
|
||||||
|
:param max_height: Максимальная высота (по умолчанию None). Если None, то считается, что максимальная высота не ограничена.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Если некорректно заданы минимальные и максимальные значения ширины
|
||||||
|
if min_width > max_width:
|
||||||
|
# - то выбрасываю исключение
|
||||||
|
raise ValueError("Минимальная ширина не может быть больше максимальной.")
|
||||||
|
|
||||||
|
# Если некорректно заданы минимальные и максимальные значения высоты
|
||||||
|
elif min_height > max_height:
|
||||||
|
# - то выбрасываю исключение
|
||||||
|
raise ValueError("Минимальная высота не может быть больше максимальной.")
|
||||||
|
|
||||||
|
# Задаю минимальные и максимальные
|
||||||
|
# - для ширины
|
||||||
|
# -- минимальное
|
||||||
|
self._min_width: int | None = min_width
|
||||||
|
# -- максимальное
|
||||||
|
self._max_width: int | None = max_width
|
||||||
|
# - для высоты
|
||||||
|
# -- минимальное
|
||||||
|
self._min_height: int | None = min_height
|
||||||
|
# -- максимальное
|
||||||
|
self._max_height: int | None = max_height
|
||||||
|
|
||||||
|
# Устанавливаю ширину
|
||||||
|
self._width: int = self._get_valid_num(width, min_width, max_width)
|
||||||
|
|
||||||
|
# Устанавливаю высоту
|
||||||
|
self._height: int = self._get_valid_num(height, min_height, max_height)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_width (self) -> int:
|
||||||
|
"""
|
||||||
|
Минимальная ширина.
|
||||||
|
:return: Значение минимальной ширины.
|
||||||
|
"""
|
||||||
|
return self._min_width
|
||||||
|
|
||||||
|
@min_width.setter
|
||||||
|
def min_width (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает минимальную ширину и пересчитывает ширину, если она выходит за новые ограничения.
|
||||||
|
:param value: Новое значение минимальной ширины.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# Если максимальная ширина ограничена и значение минимальной ширины больше максимальной ширины,
|
||||||
|
# то устанавливаю минимальную ширину равной максимальной ширине, иначе возвращаю значение
|
||||||
|
self._min_width = self._max_width if self._max_width is not None and value > self._max_width else value
|
||||||
|
|
||||||
|
# При изменении минимальной ширины пересчитываю ширину
|
||||||
|
self.width = self._width
|
||||||
|
|
||||||
|
@min_width.deleter
|
||||||
|
def min_width (self):
|
||||||
|
"""
|
||||||
|
Удаляет минимальную ширину и устанавливает минимальную ширину в 0.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._min_width = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_width (self) -> int:
|
||||||
|
"""
|
||||||
|
Максимальная ширина.
|
||||||
|
:return: Значение максимальной ширины.
|
||||||
|
"""
|
||||||
|
return self._max_width
|
||||||
|
|
||||||
|
@max_width.setter
|
||||||
|
def max_width (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает максимальную ширину и пересчитывает ширину, если она выходит за новые ограничения.
|
||||||
|
:param value: Новое значение максимальной ширины.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# Если минимальная ширина ограничена и значение максимальной ширины меньше минимальной ширины,
|
||||||
|
# то устанавливаю максимальную ширину равной минимальной ширине, иначе возвращаю значение
|
||||||
|
self._max_width = self._min_width if self._min_width is not None and value < self._min_width else value
|
||||||
|
|
||||||
|
# При изменении максимальной ширины пересчитываю ширину
|
||||||
|
self.width = self._width
|
||||||
|
|
||||||
|
@max_width.deleter
|
||||||
|
def max_width (self):
|
||||||
|
"""
|
||||||
|
Удаляет максимальную ширину.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._max_width = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_height (self) -> int:
|
||||||
|
"""
|
||||||
|
Минимальная высота.
|
||||||
|
:return: Значение минимальной высоты.
|
||||||
|
"""
|
||||||
|
return self._min_height
|
||||||
|
|
||||||
|
@min_height.setter
|
||||||
|
def min_height (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает минимальную высоту и пересчитывает высоту, если она выходит за новые ограничения.
|
||||||
|
:param value: Новое значение минимальной высоты.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# Если максимальная высота ограничена и значение минимальной высоты больше максимальной высоты,
|
||||||
|
# то устанавливаю минимальную высоту равной максимальной высоте, иначе возвращаю значение
|
||||||
|
self._min_height = self._max_height if self._max_height is not None and value > self._max_height else value
|
||||||
|
|
||||||
|
# При изменении минимальной высоты пересчитываю высоту
|
||||||
|
self.height = self._height
|
||||||
|
|
||||||
|
@min_height.deleter
|
||||||
|
def min_height (self):
|
||||||
|
"""
|
||||||
|
Удаляет минимальную высоту и устанавливает минимальную высоту в 0.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._min_height = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_height (self) -> int:
|
||||||
|
"""
|
||||||
|
Максимальная высота.
|
||||||
|
:return: Значение максимальной высоты.
|
||||||
|
"""
|
||||||
|
return self._max_height
|
||||||
|
|
||||||
|
@max_height.setter
|
||||||
|
def max_height (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает максимальную высоту и пересчитывает высоту, если она выходит за новые ограничения.
|
||||||
|
:param value: Новое значение максимальной высоты.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# Если минимальная высота ограничена и значение максимальной высоты меньше минимальной высоты,
|
||||||
|
# то устанавливаю максимальную высоту равной минимальной высоте, иначе возвращаю значение
|
||||||
|
self._max_height = self._min_height if self._min_height is not None and value < self._min_height else value
|
||||||
|
|
||||||
|
# При изменении максимальной высоты пересчитываю высоту
|
||||||
|
self.height = self._height
|
||||||
|
|
||||||
|
@max_height.deleter
|
||||||
|
def max_height (self):
|
||||||
|
"""
|
||||||
|
Удаляет максимальную высоту.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._max_height = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width (self) -> int:
|
||||||
|
"""
|
||||||
|
Ширина.
|
||||||
|
:return: Установленная ширина.
|
||||||
|
"""
|
||||||
|
return self._width
|
||||||
|
|
||||||
|
@width.setter
|
||||||
|
def width (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает ширину.
|
||||||
|
:param value: Новое значение ширины.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._width = self._get_valid_num(value, self.min_width, self.max_width)
|
||||||
|
|
||||||
|
@width.deleter
|
||||||
|
def width (self):
|
||||||
|
"""
|
||||||
|
Удаляет ширину.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._width = 0 if self._min_width is None else self._min_width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def height (self) -> int:
|
||||||
|
"""
|
||||||
|
Высота.
|
||||||
|
:return: Установленная высота.
|
||||||
|
"""
|
||||||
|
return self._height
|
||||||
|
|
||||||
|
@height.setter
|
||||||
|
def height (self, value: int):
|
||||||
|
"""
|
||||||
|
Устанавливает высоту.
|
||||||
|
:param value: Новое значение высоты.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._height = self._get_valid_num(value, self.min_height, self.max_height)
|
||||||
|
|
||||||
|
@height.deleter
|
||||||
|
def height (self):
|
||||||
|
"""
|
||||||
|
Удаляет высоту.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self._height = 0 if self._min_height is None else self._min_height
|
||||||
|
|
||||||
|
def as_str (self, delimiter: str = DEFAULT_DELIMITER) -> str:
|
||||||
|
"""
|
||||||
|
Возвращает строковое представление объекта TwoDimSize в формате "ширина:высота".
|
||||||
|
:param delimiter: Разделитель частей ширины и высоты (по умолчанию ":").
|
||||||
|
:return: Строковое представление объекта TwoDimSize.
|
||||||
|
"""
|
||||||
|
return f"{self.width}{delimiter}{self.height}"
|
||||||
|
|
||||||
|
def __str__ (self) -> str:
|
||||||
|
"""
|
||||||
|
Строковое представление объекта TwoDimSize.
|
||||||
|
:return: Строковое представление объекта TwoDimSize.
|
||||||
|
"""
|
||||||
|
return self.as_str(TwoDimSize.DEFAULT_DELIMITER)
|
||||||
|
|
||||||
|
def as_tuple (self) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Возвращает кортеж (ширина, высота).
|
||||||
|
:return: Кортеж (ширина, высота).
|
||||||
|
"""
|
||||||
|
return self.width, self.height
|
||||||
|
|
||||||
|
def __eq__ (self, other: object) -> bool:
|
||||||
|
"""
|
||||||
|
Сравнивает объект TwoDimSize с другим объектом.
|
||||||
|
:param other: Объект для сравнения.
|
||||||
|
:return: True, если объекты равны, иначе False.
|
||||||
|
"""
|
||||||
|
# Если сравниваем с объектом TwoDimSize
|
||||||
|
if isinstance(other, TwoDimSize):
|
||||||
|
# - то сравниваю ширину и высоту
|
||||||
|
return self.width == other.width and self.height == other.height
|
||||||
|
else:
|
||||||
|
# - иначе возвращаю False
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __repr__ (self) -> str:
|
||||||
|
"""
|
||||||
|
Строковое представление объекта TwoDimSize для отладки.
|
||||||
|
:return: Строковое представление объекта TwoDimSize для отладки.
|
||||||
|
"""
|
||||||
|
return f"TwoDimSize({self.width}, {self.height}, min_width={self.min_width}, max_width={self.max_width}, min_height={self.min_height}, max_height={self.max_height})"
|
||||||
|
|
||||||
|
def __hash__ (self) -> int:
|
||||||
|
"""
|
||||||
|
Хэш объекта TwoDimSize.
|
||||||
|
:return: Хэш объекта TwoDimSize.
|
||||||
|
"""
|
||||||
|
return hash((self.width, self.height))
|
||||||
|
|
||||||
|
def __copy__ (self) -> 'TwoDimSize':
|
||||||
|
"""
|
||||||
|
Копирует объект TwoDimSize.
|
||||||
|
:return: Копия объекта TwoDimSize.
|
||||||
|
"""
|
||||||
|
return TwoDimSize(self.width, self.height, self.min_width, self.max_width, self.min_height, self.max_height)
|
||||||
|
|
||||||
|
def __deepcopy__ (self, memo: dict) -> 'TwoDimSize':
|
||||||
|
"""
|
||||||
|
Глубокое копирование объекта TwoDimSize.
|
||||||
|
:param memo: Словарь для хранения копий объектов.
|
||||||
|
:return: Глубокая копия объекта TwoDimSize.
|
||||||
|
"""
|
||||||
|
# Если объект уже был скопирован
|
||||||
|
if id(self) in memo:
|
||||||
|
# - то возвращаю его копию
|
||||||
|
return memo[id(self)]
|
||||||
|
else:
|
||||||
|
# - иначе создаю копию объекта
|
||||||
|
memo[id(self)] = copy = TwoDimSize(
|
||||||
|
self.width, self.height, self.min_width, self.max_width, self.min_height, self.max_height
|
||||||
|
)
|
||||||
|
# - и возвращаю её
|
||||||
|
return copy
|
||||||
|
|
||||||
|
def __add__ (self, other: 'TwoDimSize') -> 'TwoDimSize':
|
||||||
|
"""
|
||||||
|
Складывает объект TwoDimSize с другим объектом TwoDimSize.
|
||||||
|
:param other: Объект TwoDimSize для сложения.
|
||||||
|
:return: Объект TwoDimSize, полученный после сложения.
|
||||||
|
"""
|
||||||
|
# Если другой объект является объектом TwoDimSize
|
||||||
|
if isinstance(other, TwoDimSize):
|
||||||
|
# - то складываю ширину и высоту с объектом TwoDimSize и возвращаю результат в виде объекта TwoDimSize
|
||||||
|
return TwoDimSize(
|
||||||
|
self.width + other.width, self.height + other.height, self.min_width, self.max_width,
|
||||||
|
self.min_height, self.max_height
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# - иначе выбрасываю исключение
|
||||||
|
raise TypeError("Невозможно сложить два объекта разных типов.")
|
||||||
|
|
||||||
|
def __mul__ (self, other: int) -> 'TwoDimSize':
|
||||||
|
"""
|
||||||
|
Умножает объект TwoDimSize на целое число.
|
||||||
|
:param other: Целое число для умножения.
|
||||||
|
:return: Объект TwoDimSize, полученный после умножения.
|
||||||
|
"""
|
||||||
|
# Если другой объект является целым числом
|
||||||
|
if isinstance(other, int):
|
||||||
|
# - то перемножаю ширину и высоту на целое число и возвращаю результат в виде объекта TwoDimSize
|
||||||
|
return TwoDimSize(
|
||||||
|
self.width * other, self.height * other, self.min_width, self.max_width, self.min_height,
|
||||||
|
self.max_height
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# - иначе выбрасываю исключение
|
||||||
|
raise TypeError("Невозможно перемножить объект TwoDimSize на другой объект.")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse (
|
||||||
|
text: str, delimiter: str = DEFAULT_DELIMITER, min_width: int | None = 0, max_width: int | None = None,
|
||||||
|
min_height: int | None = 0, max_height: int | None = None
|
||||||
|
) -> 'TwoDimSize':
|
||||||
|
"""
|
||||||
|
Создает объект TwoDimSize из строки.
|
||||||
|
:param max_height: Минимальная высота (по умолчанию 0). Если None, то считается, что минимальная высота не ограничена.
|
||||||
|
:param min_height: Максимальная высота (по умолчанию None). Если None, то считается, что максимальная высота не ограничена.
|
||||||
|
:param max_width: Максимальная ширина (по умолчанию None). Если None, то считается, что максимальная ширина не ограничена.
|
||||||
|
:param min_width: Минимальная ширина (по умолчанию 0). Если None, то считается, что минимальная ширина не ограничена.
|
||||||
|
:param text: Строка для создания объекта TwoDimSize.
|
||||||
|
:param delimiter: Разделитель частей ширины и высоты (по умолчанию ":").
|
||||||
|
:return: Объект TwoDimSize.
|
||||||
|
:raises ValueError: Если строка имеет неверный формат.
|
||||||
|
:raises TypeError: При попытке преобразовать строку в объект int (ширину или высоту).
|
||||||
|
"""
|
||||||
|
# Разделяю значения
|
||||||
|
split_sizes = text.split(delimiter)
|
||||||
|
|
||||||
|
# Проверяю, что массив имеет ровно два элемента
|
||||||
|
if len(split_sizes) != 2:
|
||||||
|
# - иначе выбрасываю исключение
|
||||||
|
raise ValueError("Неверный формат строки для TwoDimSize.")
|
||||||
|
|
||||||
|
# Получаю ширину и высоту
|
||||||
|
width, height = split_sizes
|
||||||
|
|
||||||
|
# Проверяю, что ширина получена
|
||||||
|
if width:
|
||||||
|
# - и перевожу ее в целое число
|
||||||
|
width = int(width)
|
||||||
|
else:
|
||||||
|
# - иначе выбрасываю исключение
|
||||||
|
raise ValueError("Неверный формат ширины в строке для TwoDimSize.")
|
||||||
|
|
||||||
|
# Проверяю, что высота получена
|
||||||
|
if height:
|
||||||
|
# - и перевожу ее в целое число
|
||||||
|
height = int(height)
|
||||||
|
else:
|
||||||
|
# - иначе выбрасываю исключение
|
||||||
|
raise ValueError("Неверный формат высоты в строке для TwoDimSize.")
|
||||||
|
|
||||||
|
# Если все проверки пройдены успешно, то создаю объект TwoDimSize с заданными шириной и высотой и возвращаю его
|
||||||
|
return TwoDimSize(width, height, min_width, max_width, min_height, max_height)
|
461
anb_python_components/types/version_info.py
Normal file
461
anb_python_components/types/version_info.py
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
# anb_python_components/types/version_info.py
|
||||||
|
import re
|
||||||
|
|
||||||
|
from anb_python_components.extensions.string_extension import StringExtension
|
||||||
|
|
||||||
|
class VersionInfo:
|
||||||
|
"""
|
||||||
|
Класс для работы с версиями.
|
||||||
|
"""
|
||||||
|
# Шаблон вывода по умолчанию.
|
||||||
|
DEFAULT_TEMPLATE: str = '#{Major}.#{Minor}.#{Release}.#{Build} #{Stage} #{StageNumber}'
|
||||||
|
|
||||||
|
def __init__ (self, major: int, minor: int, release: int, build: int, stage: str = '', stage_number: int = 0):
|
||||||
|
"""
|
||||||
|
Создание экземпляра класса VersionInfo.
|
||||||
|
:param major: Мажорная версия.
|
||||||
|
:param minor: Минорная версия.
|
||||||
|
:param release: Номер релиза.
|
||||||
|
:param build: Номер сборки.
|
||||||
|
:param stage: Стадия.
|
||||||
|
:param stage_number: Номер стадии.
|
||||||
|
"""
|
||||||
|
self.__major: int = major
|
||||||
|
self.__minor: int = minor
|
||||||
|
self.__release: int = release
|
||||||
|
self.__build: int = build
|
||||||
|
self.__stage: str = stage
|
||||||
|
self.__stage_number: int = stage_number
|
||||||
|
|
||||||
|
# Мажорная версия
|
||||||
|
@property
|
||||||
|
def major (self) -> int:
|
||||||
|
"""
|
||||||
|
Получение значения major.
|
||||||
|
:return: Значение major.
|
||||||
|
"""
|
||||||
|
return self.__major
|
||||||
|
|
||||||
|
@major.setter
|
||||||
|
def major (self, value: int):
|
||||||
|
"""
|
||||||
|
Установка значения major.
|
||||||
|
:param value: Значение major.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__major = value if value >= 0 else 0
|
||||||
|
|
||||||
|
@major.deleter
|
||||||
|
def major (self):
|
||||||
|
"""
|
||||||
|
Удаление значения major.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__major = 0
|
||||||
|
|
||||||
|
# Минорная версия
|
||||||
|
@property
|
||||||
|
def minor (self) -> int:
|
||||||
|
"""
|
||||||
|
Получение значения minor.
|
||||||
|
:return: Значение minor.
|
||||||
|
"""
|
||||||
|
return self.__minor
|
||||||
|
|
||||||
|
@minor.setter
|
||||||
|
def minor (self, value: int):
|
||||||
|
"""
|
||||||
|
Установка значения minor.
|
||||||
|
:param value: Значение minor.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__minor = value if value >= 0 else 0
|
||||||
|
|
||||||
|
@minor.deleter
|
||||||
|
def minor (self):
|
||||||
|
"""
|
||||||
|
Удаление значения minor.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__minor = 0
|
||||||
|
|
||||||
|
# Номер релиза
|
||||||
|
@property
|
||||||
|
def release (self) -> int:
|
||||||
|
"""
|
||||||
|
Получение значения release.
|
||||||
|
:return: Значение release.
|
||||||
|
"""
|
||||||
|
return self.__release
|
||||||
|
|
||||||
|
@release.setter
|
||||||
|
def release (self, value: int):
|
||||||
|
"""
|
||||||
|
Установка значения release.
|
||||||
|
:param value: Значение release.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__release = value if value >= 0 else 0
|
||||||
|
|
||||||
|
@release.deleter
|
||||||
|
def release (self):
|
||||||
|
"""
|
||||||
|
Удаление значения release.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__release = 0
|
||||||
|
|
||||||
|
# Номер сборки
|
||||||
|
@property
|
||||||
|
def bild (self) -> int:
|
||||||
|
"""
|
||||||
|
Получение значения bild.
|
||||||
|
:return: Значение bild.
|
||||||
|
"""
|
||||||
|
return self.__build
|
||||||
|
|
||||||
|
@bild.setter
|
||||||
|
def bild (self, value: int):
|
||||||
|
"""
|
||||||
|
Установка значения bild.
|
||||||
|
:param value: Значение bild.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__build = value if value >= 0 else 0
|
||||||
|
|
||||||
|
@bild.deleter
|
||||||
|
def bild (self):
|
||||||
|
"""
|
||||||
|
Удаление значения bild.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__build = 0
|
||||||
|
|
||||||
|
# Стадия
|
||||||
|
@property
|
||||||
|
def stage (self) -> str:
|
||||||
|
"""
|
||||||
|
Получение значения stage.
|
||||||
|
:return: Значение stage.
|
||||||
|
"""
|
||||||
|
return self.__stage
|
||||||
|
|
||||||
|
@stage.setter
|
||||||
|
def stage (self, value: str | None):
|
||||||
|
"""
|
||||||
|
Установка значения stage.
|
||||||
|
:param value: Значение stage.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__stage = value if value is not None else ''
|
||||||
|
|
||||||
|
@stage.deleter
|
||||||
|
def stage (self):
|
||||||
|
"""
|
||||||
|
Удаление значения stage.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__stage = ''
|
||||||
|
|
||||||
|
# Номер стадии
|
||||||
|
@property
|
||||||
|
def stage_number (self) -> int:
|
||||||
|
"""
|
||||||
|
Получение значения stage_number.
|
||||||
|
:return: Значение stage_number.
|
||||||
|
"""
|
||||||
|
return self.__stage_number
|
||||||
|
|
||||||
|
@stage_number.setter
|
||||||
|
def stage_number (self, value: int):
|
||||||
|
"""
|
||||||
|
Установка значения stage_number.
|
||||||
|
:param value: Значение stage_number.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__stage_number = value if value >= 0 else 0
|
||||||
|
|
||||||
|
@stage_number.deleter
|
||||||
|
def stage_number (self):
|
||||||
|
"""
|
||||||
|
Удаление значения stage_number.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
self.__stage_number = 0
|
||||||
|
|
||||||
|
def to_string (self, template: str = DEFAULT_TEMPLATE) -> str:
|
||||||
|
"""
|
||||||
|
Преобразование экземпляра класса VersionInfo в строку.
|
||||||
|
:param template: Шаблон для преобразования.
|
||||||
|
:return: Строка с версией.
|
||||||
|
"""
|
||||||
|
# Создание словаря для замены
|
||||||
|
template_dict = {
|
||||||
|
'#{Major}': str(self.major),
|
||||||
|
'#{Minor}': str(self.minor),
|
||||||
|
'#{Release}': str(self.release),
|
||||||
|
'#{Build}': str(self.bild),
|
||||||
|
'#{Stage}': str(self.stage),
|
||||||
|
'#{StageNumber}': str(self.stage_number) if self.stage_number > 0 else ''
|
||||||
|
}
|
||||||
|
|
||||||
|
# Замена значений в шаблоне
|
||||||
|
replaced = StringExtension.replace_all(template_dict, template)
|
||||||
|
|
||||||
|
# Удаление лишних пробелов и символов в начале и конце строки и возврат результата
|
||||||
|
return replaced.strip()
|
||||||
|
|
||||||
|
def __str__ (self) -> str:
|
||||||
|
"""
|
||||||
|
Переопределение метода __str__.
|
||||||
|
:return: Строка с версией.
|
||||||
|
"""
|
||||||
|
return self.to_string(VersionInfo.DEFAULT_TEMPLATE)
|
||||||
|
|
||||||
|
def __repr__ (self) -> str:
|
||||||
|
"""
|
||||||
|
Переопределение метода __repr__.
|
||||||
|
:return: Строка с версией.
|
||||||
|
"""
|
||||||
|
return f'VersionInfo(major={self.major}, minor={self.minor}, release={self.release}, build={self.bild}, stage={self.stage}, stage_number={self.stage_number})'
|
||||||
|
|
||||||
|
def __compare (self, other: 'VersionInfo') -> int:
|
||||||
|
"""
|
||||||
|
Сравнение версий.
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: 1, если текущая версия больше, -1, если текущая версия меньше, 0, если версии равны.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Сравнение мажорных версий. Если текущая мажорная версия больше
|
||||||
|
if self.major > other.major:
|
||||||
|
# - возвращаем 1
|
||||||
|
return 1
|
||||||
|
# Если текущая мажорная версия меньше
|
||||||
|
elif self.major < other.major:
|
||||||
|
# - возвращаем -1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
# Если мажорные версии равны, то сравниваем минорные версии. Если текущая минорная версия больше
|
||||||
|
if self.minor > other.minor:
|
||||||
|
# - возвращаем 1
|
||||||
|
return 1
|
||||||
|
# Если текущая минорная версия меньше
|
||||||
|
elif self.minor < other.minor:
|
||||||
|
# - возвращаем -1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
# Если мажорные и минорные версии равны, то сравниваем номер релиза. Если текущий номер релиза больше
|
||||||
|
if self.release > other.release:
|
||||||
|
# - возвращаем 1
|
||||||
|
return 1
|
||||||
|
# Если текущий номер релиза меньше
|
||||||
|
elif self.release < other.release:
|
||||||
|
# - возвращаем -1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
# Если мажорные, минорные и номер релиза равны, то сравниваем номер сборки. Если текущий номер сборки больше
|
||||||
|
if self.bild > other.bild:
|
||||||
|
# - возвращаем 1
|
||||||
|
return 1
|
||||||
|
# Если текущий номер сборки меньше
|
||||||
|
elif self.bild < other.bild:
|
||||||
|
# - возвращаем -1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
# Если мажорные, минорные, номер релиза и номер сборки равны, то равны и версии. Возвращаем 0.
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def __eq__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на равенство (==).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если версии равны, False, если версии не равны.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если версии равны, то возвращаем True
|
||||||
|
return self.__compare(other) == 0
|
||||||
|
|
||||||
|
def __ne__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на неравенство (!=).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если версии не равны, False, если версии равны.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если версии не равны, то возвращаем True
|
||||||
|
return self.__compare(other) != 0
|
||||||
|
|
||||||
|
def __lt__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на меньше (<).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если текущая версия меньше, False, если текущая версия больше или равна.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если текущая версия меньше, то возвращаем True
|
||||||
|
return self.__compare(other) == -1
|
||||||
|
|
||||||
|
def __gt__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на больше (>).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если текущая версия больше, False, если текущая версия меньше или равна.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если текущая версия больше, то возвращаем True
|
||||||
|
return self.__compare(other) == 1
|
||||||
|
|
||||||
|
def __le__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на меньше или равно (<=).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если текущая версия меньше или равна, False, если текущая версия больше.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если текущая версия меньше или равна, то возвращаем True
|
||||||
|
return self.__compare(other) in (0, -1)
|
||||||
|
|
||||||
|
def __ge__ (self, other: 'VersionInfo') -> bool:
|
||||||
|
"""
|
||||||
|
Сравнение версий на больше или равно (>=).
|
||||||
|
:param other: Версия для сравнения.
|
||||||
|
:return: True, если текущая версия больше или равна, False, если текущая версия меньше.
|
||||||
|
"""
|
||||||
|
# Проверка типа
|
||||||
|
if not isinstance(other, VersionInfo):
|
||||||
|
# - если other не является экземпляром VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(other)}')
|
||||||
|
|
||||||
|
# Если текущая версия больше или равна, то возвращаем True
|
||||||
|
return self.__compare(other) in (0, 1)
|
||||||
|
|
||||||
|
def in_range (
|
||||||
|
self, start: 'VersionInfo' or None = None, end: 'VersionInfo' or None = None, start_inclusive: bool = True,
|
||||||
|
end_inclusive: bool = True
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Проверка версии на принадлежность диапазону.
|
||||||
|
:param start: Начало диапазона (по умолчанию None). Если start равен None, то считается, что start не ограничен.
|
||||||
|
:param end: Конец диапазона (по умолчанию None). Если end равен None, то считается, что end не ограничен.
|
||||||
|
:param start_inclusive: Включать ли начало диапазона (по умолчанию True).
|
||||||
|
:param end_inclusive: Включать ли конец диапазона (по умолчанию True).
|
||||||
|
:return: True, если версия принадлежит диапазону, False, если версия не принадлежит диапазону.
|
||||||
|
"""
|
||||||
|
# Если start не указан
|
||||||
|
if start is None:
|
||||||
|
# - устанавливаем start_inclusive равным True
|
||||||
|
start_inclusive = True
|
||||||
|
# - устанавливаем start равным self
|
||||||
|
start = self
|
||||||
|
|
||||||
|
# Если end не указан
|
||||||
|
if end is None:
|
||||||
|
# - устанавливаем end_inclusive равным True
|
||||||
|
end_inclusive = True
|
||||||
|
# - устанавливаем end равным self
|
||||||
|
end = self
|
||||||
|
|
||||||
|
# Проверка типов
|
||||||
|
if not isinstance(start, VersionInfo) or not isinstance(end, VersionInfo):
|
||||||
|
# - если start или end не являются экземплярами VersionInfo, то выбрасываем исключение
|
||||||
|
raise TypeError(f'Невозможно сравнить тип VersionInfo с {type(start)} и {type(end)}')
|
||||||
|
|
||||||
|
# Если start совпадает с версией
|
||||||
|
if self == start:
|
||||||
|
# - если включать начало диапазона (start_inclusive), то возвращаем True, иначе False
|
||||||
|
return True if start_inclusive else False
|
||||||
|
|
||||||
|
# Если end совпадает с версией
|
||||||
|
if self == end:
|
||||||
|
# - если включать конец диапазона (end_inclusive), то возвращаем True, иначе False
|
||||||
|
return True if end_inclusive else False
|
||||||
|
|
||||||
|
# Если текущая версия находится между start и end, то возвращаем True, иначе False
|
||||||
|
return True if start < self < end else False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse (version: str) -> 'VersionInfo':
|
||||||
|
version = version.strip()
|
||||||
|
|
||||||
|
# Разбиваем строку на части по пробелам (1 часть - основная - мажор, минор, релиз, сборка,
|
||||||
|
# 2 часть - стадия и 3 - номер стадии):
|
||||||
|
# - находим позицию первого пробела
|
||||||
|
start = version.find(" ")
|
||||||
|
# - если позиция первого пробела не найдена
|
||||||
|
if start == -1:
|
||||||
|
# - устанавливаем конец строки
|
||||||
|
start = len(version)
|
||||||
|
# - находим позицию последнего пробела
|
||||||
|
end = version.rfind(" ") if start < len(version) else -1
|
||||||
|
|
||||||
|
# - получаем основную часть
|
||||||
|
main_part = version[:start].strip()
|
||||||
|
# - получаем стадию
|
||||||
|
stage = version[start:end].strip() if end > 0 else ''
|
||||||
|
# - получаем номер стадии в виде строки
|
||||||
|
stage_number_text = version[end:].strip()
|
||||||
|
# - получаем номер стадии из строки
|
||||||
|
try:
|
||||||
|
stage_number = int(stage_number_text)
|
||||||
|
except ValueError:
|
||||||
|
stage_number = 0
|
||||||
|
|
||||||
|
# Составляем регулярное выражение для парсинга базовой информации о версии
|
||||||
|
pattern = r'^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?$'
|
||||||
|
|
||||||
|
# Парсим базовую информацию о версии
|
||||||
|
matches = re.match(pattern, main_part)
|
||||||
|
|
||||||
|
# Если не удалось найти соответствие
|
||||||
|
if not matches:
|
||||||
|
# - возвращаем пустую версию
|
||||||
|
return VersionInfo(0, 0, 0, 0, stage, stage_number)
|
||||||
|
|
||||||
|
# Получаем группы из совпадения
|
||||||
|
groups = matches.groups()
|
||||||
|
|
||||||
|
# Проверяем, что найдены как минимум 2 части
|
||||||
|
if len(groups) < 2:
|
||||||
|
# - иначе возвращаем пустую версию
|
||||||
|
return VersionInfo(0, 0, 0, 0, stage, stage_number)
|
||||||
|
|
||||||
|
# Проверяем, что групп 4
|
||||||
|
if len(groups) != 4:
|
||||||
|
# - иначе возвращаем пустую версию
|
||||||
|
return VersionInfo(0, 0, 0, 0, stage, stage_number)
|
||||||
|
|
||||||
|
# Распаковываем значения
|
||||||
|
major, minor, release, build = groups
|
||||||
|
|
||||||
|
# Преобразуем строки в целые числа
|
||||||
|
major = int(major) if major else 0
|
||||||
|
minor = int(minor) if minor else 0
|
||||||
|
release = int(release) if release else 0
|
||||||
|
build = int(build) if build else 0
|
||||||
|
|
||||||
|
# Возвращаем экземпляр класса VersionInfo с полученными значениями
|
||||||
|
return VersionInfo(major, minor, release, build, stage, stage_number)
|
379
help/class_desc/classes/action_state.md
Normal file
379
help/class_desc/classes/action_state.md
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
# Класс `ActionState`
|
||||||
|
|
||||||
|
Класс `ActionState` предназначен для отслеживания состояния выполняемых действий в программе, фиксируя изменения,
|
||||||
|
происходящие в процессе выполнения, а также накапливая сообщения о событиях, успехах и ошибках. Он служит контейнером
|
||||||
|
для сохранения промежуточных состояний и обеспечивает простой интерфейс взаимодействия с ними.
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\classes\action_state.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Атрибуты и методы класса
|
||||||
|
|
||||||
|
### Атрибуты
|
||||||
|
|
||||||
|
- **`value: T`**: Хранит основное значение состояния (может быть любым объектом).
|
||||||
|
- **`__messages: list[ActionStateMessage]`**: Внутренний список сообщений, накопленных в процессе выполнения действия.
|
||||||
|
|
||||||
|
### Конструктор (`__init__`)
|
||||||
|
|
||||||
|
Принимает необязательное значение по умолчанию, которое устанавливается в качестве основного значения состояния.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `default: T | None = None`: Значение по умолчанию.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Основные методы
|
||||||
|
|
||||||
|
#### Метод `add_message`
|
||||||
|
|
||||||
|
Добавляет новое сообщение в список сообщений.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `message: ActionStateMessage`: Модель сообщения.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, ActionStateMessage, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_message(ActionStateMessage(MessageType.INFO, "Процесс запущен."))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Метод `add`
|
||||||
|
|
||||||
|
Удобный способ добавления сообщений, принимающий непосредственно тип сообщения и его текст.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `message_type: MessageType`: Тип сообщения.
|
||||||
|
- `message: str`: Сообщение.
|
||||||
|
- `flags: dict[str, bool] | None = None`: Флаги сообщения (необязательны).
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add(MessageType.WARNING, "Скорость низкая.")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `add_info`
|
||||||
|
|
||||||
|
Добавляет информационное сообщение в список состояний.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `message: str`: Текст самого информационного сообщения.
|
||||||
|
- `flags: dict[str, bool] | None = None`: Дополнительные мета-данные или признаки сообщения (например, отметка о
|
||||||
|
важности или срочности).
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_info("Начали загрузку данных.")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `add_warning`
|
||||||
|
|
||||||
|
Добавляет предупреждение в список состояний.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `message: str`: Текст предупреждения.
|
||||||
|
- `flags: dict[str, bool] | None = None`: Дополнительные флаги для конкретного предупреждения.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_warning("Не хватает оперативной памяти.")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `add_error`
|
||||||
|
|
||||||
|
Добавляет сообщение об ошибке в список состояний.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `message: str`: Текст сообщения об ошибке.
|
||||||
|
- `flags: dict[str, bool] | None = None`: Дополнительные флаги для конкретной ошибки.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_error("Не удалось установить соединение с базой данных.")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Метод `add_state`
|
||||||
|
|
||||||
|
Объединяет текущее состояние с другим состоянием, перенося его сообщения.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `state: ActionState`: Другое сообщение о состоянии.
|
||||||
|
- `clear_all_before: bool = False`: Очистить список перед добавлением (по умолчанию - False).
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
another_state = ActionState()
|
||||||
|
another_state.add_info("Дополнительная информация.")
|
||||||
|
state.add_state(another_state)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Метод `get_messages`
|
||||||
|
|
||||||
|
Возвращает список сообщений, возможно применяя фильтр по условию.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `predicate: Callable[[ActionStateMessage], bool] | None = None`: Условие выборки.
|
||||||
|
|
||||||
|
**Метод возвращает** `list[ActionStateMessage]`: список сообщений.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
errors = state.get_messages(lambda m: m.message_type == MessageType.ERROR)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `get_string_messages`
|
||||||
|
|
||||||
|
Возвращает объединённую строку сообщений, фильтруя их по определённому критерию (предикат). Полезен для визуализации
|
||||||
|
сообщений в логах или отчётах.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `predicate: Callable[[ActionStateMessage], bool] | None = None`: Функциональный предикат для фильтрации сообщений
|
||||||
|
(например, показывать только ошибки или предупреждения).
|
||||||
|
- `separator: str = "\n"`: Разделитель между сообщениями (по умолчанию новая строка).
|
||||||
|
|
||||||
|
**Метод возвращает** `str`: строка сообщений.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_error("Ошибка в сети.")
|
||||||
|
state.add_warning("Медленная скорость загрузки.")
|
||||||
|
|
||||||
|
filtered_messages = state.get_string_messages(predicate = lambda msg: msg.message_type == MessageType.ERROR)
|
||||||
|
print(filtered_messages) # "Ошибка в сети."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `has_infos`
|
||||||
|
|
||||||
|
Проверяет, имеются ли в списке сообщения информационного типа (`INFO`).
|
||||||
|
|
||||||
|
**Метод возвращает** `bool`: True, если есть, иначе False.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_info("Процесс завершён.")
|
||||||
|
|
||||||
|
if state.has_infos():
|
||||||
|
print("Имеются информационные сообщения.") # Будет выведено
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `has_warnings`
|
||||||
|
|
||||||
|
Проверяет, присутствуют ли в списке предупреждающие сообщения (`WARNING`).
|
||||||
|
|
||||||
|
**Метод возвращает** `bool`: True, если есть, иначе False.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_warning("Недостаточно памяти.")
|
||||||
|
|
||||||
|
if state.has_warnings():
|
||||||
|
print("Есть предупреждающие сообщения.") # Будет выведено
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `has_errors`
|
||||||
|
|
||||||
|
Проверяет, существуют ли в списке сообщения об ошибках (`ERROR`).
|
||||||
|
|
||||||
|
**Метод возвращает** `bool`: True, если есть, иначе False.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_error("Время ожидания истекло.")
|
||||||
|
|
||||||
|
if state.has_errors():
|
||||||
|
print("Присутствуют сообщения об ошибках.") # Будет выведено
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `clear`
|
||||||
|
|
||||||
|
Очищает список сообщений, возможно применяя условие фильтрации.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `predicate: Callable[[ActionStateMessage], bool] | None = None`: Функциональный предикат для фильтрации сообщений.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.clear(lambda m: m.message_type == MessageType.INFO)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `is_success`
|
||||||
|
|
||||||
|
Проверяет, было ли состояние успешным, основываясь на наличии ошибок и предупреждений.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `ignore_warnings: bool = False`: Игнорировать предупреждения (по умолчанию - False).
|
||||||
|
|
||||||
|
**Метод возвращает** `bool`: True, если успешно, иначе False.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
if state.is_success():
|
||||||
|
print("Операция прошла успешно.")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Метод `count`
|
||||||
|
|
||||||
|
Метод `count` позволяет получать количество сообщений в списке, потенциально применяя дополнительное условие
|
||||||
|
фильтрации (предикат). Таким образом, можно точно подсчитать число нужных сообщений (например, ошибок, предупреждений
|
||||||
|
или общих записей).
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- **`predicate: Callable[[ActionStateMessage], bool] | None = None`**: Опциональный предикат-функция, которая получает
|
||||||
|
каждое сообщение и решает, включать ли его в итоговый счётчик. Если предикат не указан, учитываются все сообщения.
|
||||||
|
|
||||||
|
**Метод возвращает** `int`: количество сообщений.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
Предположим, мы хотим посчитать количество сообщений каждого типа:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState, MessageType
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_info("Данные получены.")
|
||||||
|
state.add_warning("Память почти заполнена.")
|
||||||
|
state.add_error("Не удаётся подключиться к серверу.")
|
||||||
|
|
||||||
|
# Посчитать общее количество сообщений
|
||||||
|
total_messages = state.count()
|
||||||
|
print(total_messages) # Вывод: 3
|
||||||
|
|
||||||
|
# Посчитать количество ошибок
|
||||||
|
error_count = state.count(predicate = lambda msg: msg.message_type == MessageType.ERROR)
|
||||||
|
print(error_count) # Вывод: 1
|
||||||
|
|
||||||
|
# Посчитать количество информационных сообщений
|
||||||
|
info_count = state.count(predicate = lambda msg: msg.message_type == MessageType.INFO)
|
||||||
|
print(info_count) # Вывод: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Вспомогательные статичные методы для фильтрации сообщений
|
||||||
|
|
||||||
|
Эти методы предоставляют готовые предикаты для извлечения конкретных типов сообщений.
|
||||||
|
|
||||||
|
- `get_string_error_only() -> Callable[[ActionStateMessage], bool]`: Возвращает предикат для фильтрации только сообщений
|
||||||
|
об ошибках.
|
||||||
|
- `get_string_error_and_warning() -> Callable[[ActionStateMessage], bool]`: Возвращает предикат для фильтрации сообщений
|
||||||
|
об ошибках и предупреждениях.
|
||||||
|
- `get_string_all() -> Callable[[ActionStateMessage], bool]`: Возвращает предикат, включающий все сообщения (без
|
||||||
|
фильтрации).
|
||||||
|
|
||||||
|
**Примеры использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.classes.action_state import ActionState
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
# Получить только ошибки
|
||||||
|
only_errors = state.get_string_messages(predicate = ActionState.get_string_error_only(), separator = ", ")
|
||||||
|
|
||||||
|
# Все сообщения
|
||||||
|
all_messages = state.get_string_messages(predicate = ActionState.get_string_all())
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Класс `ActionState` играет ключевую роль в мониторинге и управлении состояниями в приложениях, позволяя контролировать
|
||||||
|
ход выполнения операций и оперативно реагировать на возникающие события и ошибки.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
26
help/class_desc/enums/message_type.md
Normal file
26
help/class_desc/enums/message_type.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Перечисление `MessageType`
|
||||||
|
|
||||||
|
Перечисление `MessageType` предназначено для классификации сообщений в программном коде. Оно помогает упорядочить типы
|
||||||
|
уведомлений и отчетов, выводимых системой. Каждый элемент перечисления обозначает определенный статус или категорию
|
||||||
|
сообщения, облегчая чтение и интерпретацию результатов выполнения программ.
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\enums\message_type.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Элементы перечисления
|
||||||
|
|
||||||
|
- **SUCCESS**: Означает успешное завершение какого-то процесса или операции.
|
||||||
|
- **INFO**: Информационные уведомления общего характера.
|
||||||
|
- **WARNING**: Предупредительные сообщения, предупреждающие о потенциальных проблемах.
|
||||||
|
- **ERROR**: Сигнал о произошедшей ошибке или сбое в выполнении программы.
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Перечисление `MessageType` способствует улучшению организации логики сообщений в приложениях, обеспечивая понятное
|
||||||
|
разделение на категории, что снижает риск путаницы и улучшает диагностику и тестирование.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
92
help/class_desc/extensions/guid_extension.md
Normal file
92
help/class_desc/extensions/guid_extension.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Класс `GUIDExtension`
|
||||||
|
|
||||||
|
Класс `GUIDExtension` предназначен для расширения функциональности работы с глобальным уникальным идентификатором
|
||||||
|
(GUID). Он предоставляет дополнительные методы для генерации новых GUID, проверки их валидности, парсинга из строк и
|
||||||
|
сравнения между собой.
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\extensions\guid_extension.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Атрибуты и методы класса
|
||||||
|
|
||||||
|
### Метод `generate`
|
||||||
|
|
||||||
|
Генерирует новый случайный GUID, следуя стандартам RFC 4122. Новый GUID создается с использованием криптографически
|
||||||
|
стойких алгоритмов генерации чисел.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.extensions.guid_extension import GUIDExtension
|
||||||
|
|
||||||
|
new_guid = GUIDExtension.generate()
|
||||||
|
print(new_guid) # Пример: 123e4567-e89b-12d3-a456-426655440000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Метод `is_equal`
|
||||||
|
|
||||||
|
Проверяет равенство двух GUID, поддерживая передачу обоих как строк, так и объектов типа `GUID`.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.extensions.guid_extension import GUIDExtension
|
||||||
|
from anb_python_components.types.guid import GUID
|
||||||
|
|
||||||
|
guid1 = "123e4567-e89b-12d3-a456-426655440000"
|
||||||
|
guid2 = GUID("123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
|
||||||
|
equal = GUIDExtension.is_equal(guid1, guid2)
|
||||||
|
print(equal) # True
|
||||||
|
```
|
||||||
|
|
||||||
|
### Метод `validate`
|
||||||
|
|
||||||
|
Проверяет, соответствует ли строка или объект правильному формату GUID.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.extensions.guid_extension import GUIDExtension
|
||||||
|
|
||||||
|
valid = GUIDExtension.validate("123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
print(valid) # True
|
||||||
|
```
|
||||||
|
|
||||||
|
### Метод `is_invalid_or_empty`
|
||||||
|
|
||||||
|
Проверяет, является ли GUID недействительным или пустым.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.extensions.guid_extension import GUIDExtension
|
||||||
|
|
||||||
|
invalid = GUIDExtension.is_invalid_or_empty("invalid-guid")
|
||||||
|
print(invalid) # True
|
||||||
|
```
|
||||||
|
|
||||||
|
### Метод `parse`
|
||||||
|
|
||||||
|
Парсит строку в GUID, возвращая объект типа `GUID`. Может вернуть пустой GUID, если передано недопустимое значение.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.extensions.guid_extension import GUIDExtension
|
||||||
|
|
||||||
|
parsed_guid = GUIDExtension.parse("123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
print(parsed_guid) # 123e4567-e89b-12d3-a456-426655440000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Класс `GUIDExtension` позволяет создать надежную систему работы с GUID в Python-проектах, облегчая генерацию, проверку и
|
||||||
|
сравнение идентификаторов. Благодаря этому обеспечивается дополнительная защита от возможных проблем с передачей
|
||||||
|
некорректных данных.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
55
help/class_desc/models/action_state_message.md
Normal file
55
help/class_desc/models/action_state_message.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Класс модели `ActionStateMessage`
|
||||||
|
|
||||||
|
Модель `ActionStateMessage` предназначена для формирования сообщений о состоянии выполненных действий в рамках проекта.
|
||||||
|
Она содержит основную информацию о результате выполненного действия, включая тип сообщения, текстовое описание и флаги (
|
||||||
|
мета-данные).
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\models\action_state_message.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Атрибуты и конструктор
|
||||||
|
|
||||||
|
### Конструктор (`__init__`)
|
||||||
|
|
||||||
|
Принимает три необязательных параметра:
|
||||||
|
|
||||||
|
- **`message_type`**: Тип сообщения, использующий перечисление `MessageType` (по умолчанию `INFO`).
|
||||||
|
- **`message`**: Сам текст сообщения (по умолчанию пустая строка).
|
||||||
|
- **`flags`**: Дополнительные метаданные или признаки сообщения (по умолчанию пустой словарь).
|
||||||
|
|
||||||
|
**Пример использования конструктора**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.models.action_state_message import ActionStateMessage, MessageType
|
||||||
|
|
||||||
|
state_message = ActionStateMessage(MessageType.SUCCESS, "Действие выполнено успешно.", {"has_errors": False})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Пример полного использования
|
||||||
|
|
||||||
|
Вот пример использования класса `ActionStateMessage`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.models.action_state_message import ActionStateMessage, MessageType
|
||||||
|
|
||||||
|
# Создание сообщения успешного действия
|
||||||
|
success_message = ActionStateMessage(MessageType.SUCCESS, "Операция завершилась успешно.")
|
||||||
|
|
||||||
|
# Создание сообщения с дополнительной информацией
|
||||||
|
info_message = ActionStateMessage(MessageType.INFO, "Начало обработки данных.", {"in_progress": False})
|
||||||
|
|
||||||
|
# Печать сообщений
|
||||||
|
print(success_message.message) # Операция завершилась успешно.
|
||||||
|
print(info_message.message) # Начало обработки данных.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Модель `ActionStateMessage` полезна для унификации способов оповещения пользователей или администратора о ходе
|
||||||
|
выполнения тех или иных процессов. Четкая структура сообщений облегчает чтение и дальнейшее развитие приложения.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
67
help/class_desc/types/guid.md
Normal file
67
help/class_desc/types/guid.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Класс `GUID`
|
||||||
|
|
||||||
|
Класс `GUID` представляет реализацию уникального глобального идентификатора (Global Unique Identifier), широко
|
||||||
|
применяемого в разработке программного обеспечения для уникальной идентификации сущностей. Данный класс добавляет
|
||||||
|
дополнительную безопасность и контроль правильности передачи и обработки уникальных идентификаторов.
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\types\guid.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Атрибуты и методы класса
|
||||||
|
|
||||||
|
### Свойства и конструкторы
|
||||||
|
|
||||||
|
- **Атрибут `EMPTY`**: Представляет пустое значение GUID (стандартное значение для незаданных GUID).
|
||||||
|
- **Конструктор (`__init__`)**: Осуществляет создание нового экземпляра GUID, принимает либо строку, либо другой
|
||||||
|
экземпляр GUID и проверяет правильность передаваемых данных.
|
||||||
|
|
||||||
|
### Специальные методы
|
||||||
|
|
||||||
|
- **Метод `__str__`**: Предоставляет текстовое представление текущего GUID.
|
||||||
|
- **Метод `__eq__`**: Определяет правило сравнения двух GUID друг с другом.
|
||||||
|
|
||||||
|
### Вспомогательные методы
|
||||||
|
|
||||||
|
- **Метод `validate_str`**: Проверяет строку на соответствие стандартному формату GUID (регулярные выражения
|
||||||
|
используются для проверки синтаксиса).
|
||||||
|
|
||||||
|
## Исключения
|
||||||
|
|
||||||
|
- **Ошибка `WrongTypeException`**: Генератор исключений срабатывает при передаче неверного типа данных или нарушении
|
||||||
|
формата GUID.
|
||||||
|
|
||||||
|
## Пример использования
|
||||||
|
|
||||||
|
Создание экземпляра GUID:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.guid import GUID
|
||||||
|
|
||||||
|
my_guid = GUID("123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
print(my_guid) # 123e4567-e89b-12d3-a456-426655440000
|
||||||
|
```
|
||||||
|
|
||||||
|
Сравнение двух GUID:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.guid import GUID
|
||||||
|
|
||||||
|
first_guid = GUID("123e4567-e89b-12d3-a456-426655440000")
|
||||||
|
second_guid = GUID("00000000-0000-0000-0000-000000000000")
|
||||||
|
|
||||||
|
if first_guid == second_guid:
|
||||||
|
print("GUID совпадают")
|
||||||
|
else:
|
||||||
|
print("GUID различаются")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Класс `GUID` позволяет грамотно управлять уникальным идентификатором, обеспечивая автоматическое преобразование и
|
||||||
|
проверку корректности данных. Такой подход минимизирует вероятность ошибок и улучшает надежность приложения.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
165
help/class_desc/types/two_dim_size.md
Normal file
165
help/class_desc/types/two_dim_size.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# Класс `TwoDimSize`
|
||||||
|
|
||||||
|
Класс `TwoDimSize` предназначен для работы с двумерными размерами, такими как ширина и высота. Он предоставляет ряд
|
||||||
|
инструментов для эффективного управления и обработки размеров, включая ограничение минимальных/максимальных границ,
|
||||||
|
арифметические операции и удобное представление в строковом виде.
|
||||||
|
|
||||||
|
## Основная информация
|
||||||
|
|
||||||
|
- **Имя файла**: anb_python_components\types\two_dim_size.py
|
||||||
|
- **Автор**: Александр Бабаев
|
||||||
|
- **Версия**: 1.0.0
|
||||||
|
- **Дата начала поддержки**: с версии 1.0
|
||||||
|
|
||||||
|
## Атрибуты и методы класса
|
||||||
|
|
||||||
|
### Конструктор (`__init__`)
|
||||||
|
|
||||||
|
Принимает начальные значения ширины и высоты, а также минимальные и максимальные границы, если требуется ограничить
|
||||||
|
диапазон значений.
|
||||||
|
|
||||||
|
**Параметры**:
|
||||||
|
|
||||||
|
- `width: int`: Начальная ширина (по умолчанию 0).
|
||||||
|
- `height: int`: Начальная высота (по умолчанию 0).
|
||||||
|
- `min_width: int | None = 0`, `min_height: int | None = 0`: Минимальное значение ширины и высоты (по умолчанию, `0`).
|
||||||
|
При значении `None` считаются неограниченными.
|
||||||
|
- `max_width: int | None = None`, `max_height: int | None = None`: Максимальное значение ширины и высоты (по умолчанию,
|
||||||
|
`None`). При значении `None` считаются неограниченными.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize(800, 600, min_width = 400, max_width = 1200)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Свойства класса
|
||||||
|
|
||||||
|
Свойства позволяют гибко устанавливать и считывать значения ширины и высоты, автоматически соблюдая введённые
|
||||||
|
ограничения. Рассмотрим подробнее каждый из них.
|
||||||
|
|
||||||
|
#### Свойство `width`
|
||||||
|
|
||||||
|
Управляет значением ширины, выполняя необходимую проверку ограничений при установке.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize(min_width = 400)
|
||||||
|
size.width = 500
|
||||||
|
print(size.width) # Вывод: 500
|
||||||
|
size.width = 300
|
||||||
|
print(size.width) # Вывод: 400
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Свойство `height`
|
||||||
|
|
||||||
|
Аналогично свойствам ширины, управляет значением высоты.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize(max_height = 1000)
|
||||||
|
size.height = 200
|
||||||
|
print(size.height) # Вывод: 200
|
||||||
|
size.height = 1200
|
||||||
|
print(size.height) # Вывод: 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Свойства границ (`min_width`, `max_width`, `min_height`, `max_height`)
|
||||||
|
|
||||||
|
Эти свойства отвечают за изменение граничных значений ширины и высоты, контролируя их согласованность изменений
|
||||||
|
(например, максимальная граница не должна быть меньше минимальной).
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize()
|
||||||
|
|
||||||
|
# И тут мы вспомнили (а как обычно и бывает!), что забыли дать ограничения! =)
|
||||||
|
# Установим минимальную ширину
|
||||||
|
size.min_width = 500
|
||||||
|
# и максимальную высоту
|
||||||
|
size.max_height = 1000
|
||||||
|
|
||||||
|
# Включаем внутреннего Пушного и запускаем рубрику "Эксперименты"
|
||||||
|
size.height = 600
|
||||||
|
size.width = 600
|
||||||
|
print(str(size)) # Вывод: 600:600
|
||||||
|
size.height = 900
|
||||||
|
size.width = 100
|
||||||
|
print(str(size)) # Вывод: 500:900
|
||||||
|
# Мы в этом примере задали число, меньшее минимальной ширины, вот она и вернула минимальную.
|
||||||
|
# Так же будет, если мы превысим максимальную высоту
|
||||||
|
size.height = 1200
|
||||||
|
size.width = 600
|
||||||
|
print(str(size)) # Вывод: 600:1000
|
||||||
|
# И даже если не соблюдём оба
|
||||||
|
size.height = 100
|
||||||
|
size.width = 1200
|
||||||
|
print(str(size)) # Вывод: 500:1000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ключевые методы
|
||||||
|
|
||||||
|
#### Метод `as_str`
|
||||||
|
|
||||||
|
Форматирует объект в строку вида `"ширина:высота"`, используя разделитель (по умолчанию двоеточие).
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize(800, 600)
|
||||||
|
print(size.as_str()) # Вывод: 800:600
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Метод `as_tuple`
|
||||||
|
|
||||||
|
Возвращает размеры в виде кортежа `(ширина, высота)`.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize(800, 600)
|
||||||
|
print(size.as_tuple()) # Вывод: (800, 600)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Метод `parse`
|
||||||
|
|
||||||
|
Анализирует строку вида `"ширина:высота"` и создает объект `TwoDimSize` из нее.
|
||||||
|
|
||||||
|
**Пример использования**:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from anb_python_components.types.two_dim_size import TwoDimSize
|
||||||
|
|
||||||
|
size = TwoDimSize.parse("1920:1080")
|
||||||
|
print(size.width) # 1920
|
||||||
|
print(size.height) # 1080
|
||||||
|
```
|
||||||
|
|
||||||
|
### Магические методы
|
||||||
|
|
||||||
|
- `__str__`, `__repr__`: Отвечают за отображение объекта в строковом виде.
|
||||||
|
- `__eq__`: Определяет равенство двух объектов по ширине и высоте.
|
||||||
|
- `__hash__`: Позволяет использовать объект в структурах вроде множества или словаря.
|
||||||
|
- `__add__`, `__mul__`: Поддерживают сложение и умножение размеров соответственно.
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Класс `TwoDimSize` идеально подходит для работы с размерами графических объектов, элементами UI и подобными ситуациями,
|
||||||
|
требующими четкого контроля за пределами размеров и легкости манипуляций.
|
||||||
|
|
||||||
|
[На главную](../../index.md)
|
@@ -8,11 +8,18 @@
|
|||||||
|
|
||||||
## Описание интерфейсов, классов и перечислений:
|
## Описание интерфейсов, классов и перечислений:
|
||||||
|
|
||||||
|
### Классы
|
||||||
|
|
||||||
|
**Расположение модулей**: anb_python_components\classes\*
|
||||||
|
|
||||||
|
- [класс `ActionState`](class_desc/classes/action_state.md)
|
||||||
|
|
||||||
### Перечисления
|
### Перечисления
|
||||||
|
|
||||||
**Расположение модулей**: anb_python_components\enums\*
|
**Расположение модулей**: anb_python_components\enums\*
|
||||||
|
|
||||||
- [перечисление `NotBoolAction`](class_desc/enums/not_bool_action.md)
|
- [перечисление `NotBoolAction`](class_desc/enums/not_bool_action.md)
|
||||||
|
- [перечисление `MessageType`](class_desc/enums/message_type.md)
|
||||||
|
|
||||||
### Исключения
|
### Исключения
|
||||||
|
|
||||||
@@ -29,3 +36,17 @@
|
|||||||
- [класс `BoolExtension`](class_desc/extensions/bool_extension.md)
|
- [класс `BoolExtension`](class_desc/extensions/bool_extension.md)
|
||||||
- [класс `TypeExtension`](class_desc/extensions/type_extension.md)
|
- [класс `TypeExtension`](class_desc/extensions/type_extension.md)
|
||||||
- [класс `ArrayExtension`](class_desc/extensions/array_extension.md)
|
- [класс `ArrayExtension`](class_desc/extensions/array_extension.md)
|
||||||
|
- [класс `GUIDExtension`](class_desc/extensions/guid_extension.md)
|
||||||
|
|
||||||
|
### Типы
|
||||||
|
|
||||||
|
**Расположение модулей**: anb_python_components\types\*
|
||||||
|
|
||||||
|
- [тип `GUID`](class_desc/types/guid.md)
|
||||||
|
- [тип `TwoDimSize`](class_desc/types/two_dim_size.md)
|
||||||
|
|
||||||
|
### Модели
|
||||||
|
|
||||||
|
**Расположение модулей**: anb_python_components\models\*
|
||||||
|
|
||||||
|
- [модель `ActionStateMessage`](class_desc/models/action_state_message.md)
|
@@ -1 +1 @@
|
|||||||
# anb_python_components/__init__.py
|
# tests/__init__.py
|
1
tests/classes/__init__.py
Normal file
1
tests/classes/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# tests/classes/__init__.py
|
138
tests/classes/action_state_test.py
Normal file
138
tests/classes/action_state_test.py
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# action_state_test.py
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from anb_python_components.classes.action_state import ActionState, ActionStateMessage, MessageType
|
||||||
|
|
||||||
|
class ActionStateTest(unittest.TestCase):
|
||||||
|
def test_init (self):
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
self.assertIsInstance(state, ActionState)
|
||||||
|
self.assertFalse(state.value)
|
||||||
|
state.value = True
|
||||||
|
self.assertTrue(state.value)
|
||||||
|
|
||||||
|
def test_add_message (self):
|
||||||
|
message = ActionStateMessage(MessageType.INFO, "Test message")
|
||||||
|
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
state.add_message(message)
|
||||||
|
|
||||||
|
self.assertEqual(1, state.count())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_test_state (no_warning: bool = False, no_error: bool = False, state_value: bool = False) -> ActionState[
|
||||||
|
bool]:
|
||||||
|
"""
|
||||||
|
Генерирует тестовое состояние.
|
||||||
|
:param no_warning: Без предупреждений.
|
||||||
|
:param no_error: Без ошибок.
|
||||||
|
:param state_value: Значение состояния.
|
||||||
|
:return: Тестовое состояние.
|
||||||
|
"""
|
||||||
|
state = ActionState[bool](False)
|
||||||
|
|
||||||
|
state.add_info("Тестовое сообщение1")
|
||||||
|
if not no_error:
|
||||||
|
state.add_error("Тестовое сообщение2")
|
||||||
|
state.add_info("Тестовое сообщение3")
|
||||||
|
state.add_info("Тестовое сообщение4")
|
||||||
|
if not no_warning:
|
||||||
|
state.add_warning("Тестовое сообщение5")
|
||||||
|
state.add_info("Тестовое сообщение6")
|
||||||
|
state.add_info("Тестовое сообщение7")
|
||||||
|
state.add_info("Тестовое сообщение8")
|
||||||
|
if not no_warning:
|
||||||
|
state.add_warning("Тестовое сообщение9")
|
||||||
|
if not no_error:
|
||||||
|
state.add_error("Тестовое сообщение10")
|
||||||
|
|
||||||
|
state.value = state_value
|
||||||
|
|
||||||
|
return state
|
||||||
|
|
||||||
|
def test_add_state (self):
|
||||||
|
state1 = ActionStateTest.get_test_state(True, True, True)
|
||||||
|
|
||||||
|
state2 = ActionStateTest.get_test_state(state_value = False)
|
||||||
|
|
||||||
|
state1.add_state(state2)
|
||||||
|
|
||||||
|
self.assertEqual(16, state1.count())
|
||||||
|
|
||||||
|
def test_get_messages (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
state_messages = state.get_messages()
|
||||||
|
|
||||||
|
self.assertEqual(10, len(state_messages))
|
||||||
|
|
||||||
|
count_errors = 0
|
||||||
|
|
||||||
|
for message in state_messages:
|
||||||
|
if message.message_type == MessageType.ERROR:
|
||||||
|
count_errors += 1
|
||||||
|
|
||||||
|
self.assertEqual(2, count_errors)
|
||||||
|
|
||||||
|
def test_get_string_messages (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
state_message_string = state.get_string_messages(ActionState.get_string_error_only())
|
||||||
|
|
||||||
|
need_string = "Тестовое сообщение2\nТестовое сообщение10"
|
||||||
|
|
||||||
|
self.assertEqual(state_message_string, need_string)
|
||||||
|
|
||||||
|
def test_has_infos (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
self.assertTrue(state.has_infos())
|
||||||
|
|
||||||
|
def test_has_warnings (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
self.assertTrue(state.has_warnings())
|
||||||
|
|
||||||
|
def test_has_errors (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
self.assertTrue(state.has_errors())
|
||||||
|
|
||||||
|
def test_is_success (self):
|
||||||
|
state_fail = ActionStateTest.get_test_state()
|
||||||
|
state_success = ActionStateTest.get_test_state(no_warning = True, no_error = True)
|
||||||
|
state_success_no_warning = ActionStateTest.get_test_state(no_error = True)
|
||||||
|
|
||||||
|
self.assertTrue(state_success.is_success())
|
||||||
|
self.assertTrue(state_success_no_warning.is_success(True))
|
||||||
|
self.assertFalse(state_fail.is_success())
|
||||||
|
|
||||||
|
def test_clear (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
state.clear(lambda message: message.message_type == MessageType.WARNING)
|
||||||
|
|
||||||
|
self.assertEqual(8, len(state.get_messages()))
|
||||||
|
|
||||||
|
state.clear()
|
||||||
|
|
||||||
|
self.assertEqual(0, len(state.get_messages()))
|
||||||
|
|
||||||
|
def test_count (self):
|
||||||
|
state = ActionStateTest.get_test_state()
|
||||||
|
|
||||||
|
count_all = state.count()
|
||||||
|
count_warnings = state.count(lambda message: message.message_type == MessageType.WARNING)
|
||||||
|
count_errors = state.count(lambda message: message.message_type == MessageType.ERROR)
|
||||||
|
count_errors_and_warnings = state.count(
|
||||||
|
lambda message: message.message_type == MessageType.WARNING or message.message_type == MessageType.ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(10, count_all)
|
||||||
|
self.assertEqual(2, count_errors)
|
||||||
|
self.assertEqual(2, count_warnings)
|
||||||
|
self.assertEqual(4, count_errors_and_warnings)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@@ -1 +1 @@
|
|||||||
# anb_python_components/extensions/__init__.py
|
# tests/extensions/__init__.py
|
@@ -1,10 +1,9 @@
|
|||||||
# string_extension_test.py
|
# bool_extension_test.py
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from anb_python_components.extensions.bool_extension import *
|
from anb_python_components.extensions.bool_extension import *
|
||||||
|
|
||||||
|
|
||||||
class BoolExtensionTest(unittest.TestCase):
|
class BoolExtensionTest(unittest.TestCase):
|
||||||
def test_to_str (self):
|
def test_to_str (self):
|
||||||
self.assertEqual(BoolExtension.to_str(True, "да", "нет"), "да")
|
self.assertEqual(BoolExtension.to_str(True, "да", "нет"), "да")
|
||||||
@@ -16,6 +15,5 @@ class BoolExtensionTest(unittest.TestCase):
|
|||||||
def test_any_true (self):
|
def test_any_true (self):
|
||||||
self.assertTrue(BoolExtension.any_true([False, True, False, True, True, False, False]))
|
self.assertTrue(BoolExtension.any_true([False, True, False, True, True, False, False]))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
1
tests/types/__init__.py
Normal file
1
tests/types/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# tests/types/__init__.py
|
78
tests/types/guid_test.py
Normal file
78
tests/types/guid_test.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# anb_python_components/types/guid.py
|
||||||
|
import re
|
||||||
|
|
||||||
|
from anb_python_components.exceptions.wrong_type_exception import WrongTypeException
|
||||||
|
|
||||||
|
class GUID:
|
||||||
|
"""
|
||||||
|
Тип GUID.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Константа пустого GUID
|
||||||
|
EMPTY: str = "00000000-0000-0000-0000-000000000000"
|
||||||
|
|
||||||
|
def __init__ (self, guid = EMPTY):
|
||||||
|
"""
|
||||||
|
Инициализация расширения.
|
||||||
|
:param guid: str | GUID - Передаваемый GUID
|
||||||
|
"""
|
||||||
|
# Проверка типа аргумента guid
|
||||||
|
# - если аргумент не является строкой
|
||||||
|
if not isinstance(guid, str):
|
||||||
|
# -- если аргумент является экземпляром GUID
|
||||||
|
if isinstance(guid, GUID):
|
||||||
|
# - преобразуем его в строку
|
||||||
|
guid = str(guid)
|
||||||
|
else:
|
||||||
|
# -- иначе генерируем исключение
|
||||||
|
raise WrongTypeException("Неверный тип аргумента!", "GUID", str(type(guid)), "guid")
|
||||||
|
|
||||||
|
# Проверка GUID на валидность
|
||||||
|
if not self.validate_str(guid):
|
||||||
|
# и если GUID невалидный, то генерируем исключение
|
||||||
|
raise WrongTypeException("Неверный формат GUID!", "GUID", guid, "guid")
|
||||||
|
|
||||||
|
# Инициализируем приватный атрибут __value (текстовое представление хранящегося GUID)
|
||||||
|
self.__value = guid
|
||||||
|
|
||||||
|
def __str__ (self):
|
||||||
|
"""
|
||||||
|
Переопределение метода __str__.
|
||||||
|
:return: Текстовое представление GUID.
|
||||||
|
"""
|
||||||
|
return self.__value if self.__value else self.EMPTY
|
||||||
|
|
||||||
|
def __eq__ (self, other):
|
||||||
|
"""
|
||||||
|
Переопределение метода __eq__.
|
||||||
|
:param other: Объект для сравнения.
|
||||||
|
:return: True, если GUID равны, иначе False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Если аргумент не является экземпляром GUID
|
||||||
|
if not isinstance(other, GUID):
|
||||||
|
# - генерируем исключение
|
||||||
|
raise WrongTypeException("Неверный тип аргумента!", "GUID", type(other), "other")
|
||||||
|
|
||||||
|
# Преобразование второго аргумента в строку
|
||||||
|
other_str = str(other)
|
||||||
|
|
||||||
|
# Сравниваем строки
|
||||||
|
return self.__value == other_str
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def validate_str (guid: str | None) -> bool:
|
||||||
|
"""
|
||||||
|
Проверка строки на валидность GUID.
|
||||||
|
:return: True, если GUID валидный, иначе False.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Проверка на пустоту
|
||||||
|
if not guid:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Регулярное выражение для проверки формата GUID
|
||||||
|
pattern = r'^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$'
|
||||||
|
|
||||||
|
# Проверка на соответствие формату
|
||||||
|
return bool(re.fullmatch(pattern, guid))
|
1
tests/types/two_dim_size_test.py
Normal file
1
tests/types/two_dim_size_test.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# two_dim_size_test.py
|
51
tests/types/version_info_test.py
Normal file
51
tests/types/version_info_test.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# version_info_test.py
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from anb_python_components.types.version_info import VersionInfo
|
||||||
|
|
||||||
|
class VersionInfoTest(unittest.TestCase):
|
||||||
|
def test_init (self):
|
||||||
|
version_info = VersionInfo(1, 2, 3, 4, "Тестовая версия", 1)
|
||||||
|
version_info_str = '1.2.3.4 Тестовая версия 1'
|
||||||
|
|
||||||
|
self.assertEqual(version_info_str, str(version_info))
|
||||||
|
|
||||||
|
def test_math (self):
|
||||||
|
version_info_1 = VersionInfo(1, 2, 3, 4, "Тестовая версия", 1)
|
||||||
|
version_info_2 = VersionInfo(1, 2, 3, 4, "Тестовая версия", 1)
|
||||||
|
version_info_3 = VersionInfo(2, 1, 3, 10, "Тестовая версия", 2)
|
||||||
|
version_info_4 = VersionInfo(3, 5, 3, 12, "Тестовая версия", 3)
|
||||||
|
|
||||||
|
self.assertTrue(version_info_1 == version_info_2)
|
||||||
|
self.assertTrue(version_info_3 > version_info_2)
|
||||||
|
self.assertTrue(version_info_3 >= version_info_1)
|
||||||
|
self.assertTrue(version_info_1 < version_info_4)
|
||||||
|
self.assertTrue(version_info_3.in_range(version_info_1, version_info_4))
|
||||||
|
self.assertFalse(version_info_3.in_range(version_info_1, version_info_3, end_inclusive = False))
|
||||||
|
self.assertTrue(version_info_3.in_range(version_info_1))
|
||||||
|
self.assertTrue(version_info_3.in_range())
|
||||||
|
|
||||||
|
def test_parse (self):
|
||||||
|
str_ver_1 = '1.2.3.4 Тестовая 1'
|
||||||
|
version_info_1 = VersionInfo(1, 2, 3, 4, "Тестовая", 1)
|
||||||
|
str_ver_2 = "1.2.3.4 Тестовая"
|
||||||
|
version_info_2 = VersionInfo(1, 2, 3, 4, "Тестовая", 0)
|
||||||
|
str_ver_3 = "1.2.3.4"
|
||||||
|
version_info_3 = VersionInfo(1, 2, 3, 4, "", 0)
|
||||||
|
str_ver_4 = "1.2.3 Тестовая 1"
|
||||||
|
version_info_4 = VersionInfo(1, 2, 3, 0, "Тестовая", 1)
|
||||||
|
str_ver_5 = "1.2 Тестовая 1"
|
||||||
|
version_info_5 = VersionInfo(1, 2, 0, 0, "Тестовая", 1)
|
||||||
|
str_ver_6 = "1 Тестовая 1"
|
||||||
|
version_info_6 = VersionInfo(1, 0, 0, 0, "Тестовая", 1)
|
||||||
|
|
||||||
|
self.assertEqual(version_info_1, VersionInfo.parse(str_ver_1))
|
||||||
|
self.assertEqual(version_info_2, VersionInfo.parse(str_ver_2))
|
||||||
|
self.assertEqual(version_info_3, VersionInfo.parse(str_ver_3))
|
||||||
|
self.assertEqual(version_info_4, VersionInfo.parse(str_ver_4))
|
||||||
|
self.assertEqual(version_info_5, VersionInfo.parse(str_ver_5))
|
||||||
|
self.assertEqual(version_info_6, VersionInfo.parse(str_ver_6))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Reference in New Issue
Block a user