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\*
|
||||
|
||||
- [перечисление `NotBoolAction`](class_desc/enums/not_bool_action.md)
|
||||
- [перечисление `MessageType`](class_desc/enums/message_type.md)
|
||||
|
||||
### Исключения
|
||||
|
||||
@@ -28,4 +35,18 @@
|
||||
- [класс `StringExtension`](class_desc/extensions/string_extension.md)
|
||||
- [класс `BoolExtension`](class_desc/extensions/bool_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,21 +1,19 @@
|
||||
# string_extension_test.py
|
||||
# bool_extension_test.py
|
||||
|
||||
import unittest
|
||||
|
||||
from anb_python_components.extensions.bool_extension import *
|
||||
|
||||
|
||||
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(False, "да", "нет"), "нет")
|
||||
|
||||
def test_true_count(self):
|
||||
|
||||
def test_true_count (self):
|
||||
self.assertEqual(BoolExtension.true_count([False, True, False, True, True, False, False]), 3)
|
||||
|
||||
def test_any_true(self):
|
||||
|
||||
def test_any_true (self):
|
||||
self.assertTrue(BoolExtension.any_true([False, True, False, True, True, False, False]))
|
||||
|
||||
|
||||
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