This commit is contained in:
2025-10-04 15:18:48 +03:00
parent 22fa3b0445
commit 2d0a800598
12 changed files with 411 additions and 1 deletions

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Тест ArrayExtension" 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/extensions" />
<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="&quot;&quot;" />
<option name="_new_target" value="&quot;$PROJECT_DIR$/tests/extensions/array_extension_test.py&quot;" />
<option name="_new_targetType" value="&quot;PATH&quot;" />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Тест TypeExtension" 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/extensions" />
<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="&quot;&quot;" />
<option name="_new_target" value="&quot;$PROJECT_DIR$/tests/extensions/type_extension_test.py&quot;" />
<option name="_new_targetType" value="&quot;PATH&quot;" />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1 @@
# anb_python_components/classes/__init__.py

View File

@@ -0,0 +1,66 @@
# anb_python_components/classes/guid.py
import re
from anb_python_components.exceptions.wrong_type_exception import WrongTypeException
# Константа пустого GUID
GUID_EMPTY: str = "00000000-0000-0000-0000-000000000000"
class GUID:
def __init__(self, guid: str = GUID_EMPTY):
"""
Инициализация расширения.
:param 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 GUID_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))

View File

@@ -0,0 +1 @@
# anb_python_components/exceptions/__init__.py

View File

@@ -0,0 +1,20 @@
# anb_python_components/exceptions/wrong_type_exception.py
class WrongTypeException(Exception):
"""
Ошибка, возникающая при попытке присвоить значение другого типа данным полям.
"""
def __init__(self, message: str = None, type_name: str = None, real_type_name: str = None, var_name: str = None):
"""
Инициализация экземпляра класса WrongTypeException.
:param message: Сообщение об ошибке.
:param type_name: Имя типа (по умолчанию None).
:param real_type_name: Имя реального типа (по умолчанию None).
:param var_name: Имя переменной (по умолчанию None).
"""
super().__init__(message)
self.message = message
self.type_name = type_name,
self.real_type_name = real_type_name,
self.var_name = var_name

View File

@@ -0,0 +1,35 @@
# anb_python_components/extensions/array_extension.py
from anb_python_components.extensions.string_extension import StringExtension
class ArrayExtension:
"""
Класс расширения для работы с массивами.
"""
def __init__(self):
"""
Инициализация расширения.
"""
pass
@staticmethod
def remove_empties(array: list[str], re_sort: bool = False) -> list[str]:
"""
Удаляет пустые строки из массива.
:param array: Массив строк.
:param re_sort: Пересортировать массив после удаления пустых строк.
:return: Массив строк без пустых строк.
"""
# Удаляем пустые строки
result = list(filter(lambda x: not StringExtension.is_none_or_whitespace(x), array))
# Если нужно пересортировать массив
if re_sort:
# - сортируем массив
result.sort()
# Возвращаем результат
return result

View File

@@ -0,0 +1,123 @@
# anb_python_components/extensions/guid_extension.py
import secrets
from anb_python_components.classes.guid import GUID, GUID_EMPTY
from anb_python_components.exceptions.wrong_type_exception import WrongTypeException
class GUIDExtension:
"""
Класс GUIDExtension реализует расширение для работы с GUID.
"""
def __init__(self):
"""
Инициализация расширения.
"""
pass
@staticmethod
def generate() -> GUID:
"""
Генерирует уникальный идентификатор GUID согласно стандарту RFC 4122.
"""
# Генерация отдельных компонентов GUID
time_low = secrets.randbits(32) & 0xffffffff
time_mid = secrets.randbits(16) & 0xffff
time_hi_and_version = ((secrets.randbits(12) << 4) | 0x4000) & 0xffff
clock_seq_hi_and_reserved = ((secrets.randbits(14) << 2) | 0x8000) & 0xffff
node_id = secrets.randbits(48) & 0xffffffffffff
# Объединение компонентов в единый GUID
guid_parts = [
time_low >> 16, time_low & 0xffff,
time_mid,
time_hi_and_version,
clock_seq_hi_and_reserved,
node_id >> 32, (node_id >> 16) & 0xffff, node_id & 0xffff
]
# Форматируем компоненты в виде строки GUID
guid_str = "-".join([
"%08x" % guid_parts[0],
"%04x" % guid_parts[1],
"%04x" % guid_parts[2],
"%04x" % guid_parts[3],
("%04x%04x%04x" % tuple(guid_parts[4:])),
])
# Возвращаем экземпляр GUID
return GUID(guid_str)
@staticmethod
def is_equal(guid1: str | GUID, guid2: str | GUID) -> bool:
# Если guid1 не является GUID или строкой
if not isinstance(guid1, GUID) or not isinstance(guid1, str):
# - генерируем исключение
raise WrongTypeException("Неверный тип аргумента!", "GUID|str", var_name="guid1")
# Если guid2 не является GUID или строкой
if not isinstance(guid2, GUID) or not isinstance(guid2, str):
# - генерируем исключение
raise WrongTypeException("Неверный тип аргумента!", "GUID|str", var_name="guid2")
# Если guid1 является строкой
if not isinstance(guid1, GUID):
# - преобразуем её в GUID
guid1 = GUID(guid1)
# Если guid2 является строкой
if not isinstance(guid2, GUID):
# - преобразуем её в GUID
guid2 = GUID(guid2)
# Сравниваем GUID
return guid1 == guid2
@staticmethod
def validate(guid: str | GUID) -> bool:
"""
Проверка GUID на валидность.
:param guid: GUID для проверки.
:return: True, если GUID валидный, иначе False.
"""
# Если guid не является строкой, то преобразуем его в неё
guid = guid if isinstance(guid, str) else str(guid)
# Проверяем GUID
return bool(GUID.validate_str(guid))
@staticmethod
def is_invalid_or_empty(guid: str | GUID) -> bool:
"""
Проверка GUID на валидность и не пустоту.
:param guid: Класс или строка GUID для проверки.
:return: True, если GUID не валидный или пустой, иначе False.
"""
# Если guid не является строкой, то преобразуем его в неё
guid = guid if isinstance(guid, str) else str(guid)
# Проверяем GUID
return not GUID.validate_str(guid) or guid == GUID_EMPTY
@classmethod
def parse(cls, guid_string: str, empty_if_not_valid: bool = True) -> GUID:
"""
Парсинг GUID из строки.
:param guid_string: Строка GUID.
:param empty_if_not_valid: Если True, то возвращается пустой GUID, если GUID недействителен.
"""
# Проверяем строку на соответствие формату GUID
if cls.validate(guid_string):
# - если GUID действителен, возвращаем экземпляр GUID
return GUID(guid_string)
# Если же GUID недействителен и запрещено выбрасывать исключение
if empty_if_not_valid:
# -- то возвращаем пустой GUID
return GUID(GUID_EMPTY)
else:
# -- иначе выбрасываем исключение
raise WrongTypeException('Предан неверный GUID / Wrong GUID.')

View File

@@ -0,0 +1,63 @@
# Класс `WrongTypeException`
Класс `WrongTypeException` представляет собой настраиваемое исключение, возникающее при некорректном присваивании
значения другому типу данных. Обычно такое исключение применяется для контроля целостности типов в строгих системах
разработки программного обеспечения, предотвращая потенциальные проблемы и неопределённое поведение программы.
## Основная информация
- **Имя файла**: anb_python_components\exceptions\wrong_type_exception.py
- **Автор**: Александр Бабаев
- **Версия**: 1.0.0
- **Дата начала поддержки**: с версии 1.0
## Атрибуты и методы класса
### Конструктор (`__init__`)
Создаёт экземпляр исключения, принимая необязательные параметры для детального описания ошибки.
Параметры конструктора:
- `message`: Пользовательское сообщение об ошибке.
- `type_name`: Ожидаемый тип данных (например, `int`, `float`, `str`).
- `real_type_name`: Реальный тип данных, который был использован ошибочно.
- `var_name`: Название переменной, вызвавшей ошибку.
Пример использования:
```python
from anb_python_components.exceptions.wrong_type_exception import WrongTypeException
# Допустим, задана какая-то функция
def some_function(value):
# в этой функции стоит проверка на тип
if not isinstance(value, int):
# и в случае неудачной проверки выбрасывается исключение
raise WrongTypeException("Неверный тип!", "int", type(value), "value")
# Пусть эта функция для примера просто добавляет 1 к value
return value + 1
try:
# Зададим переменную a как произвольную строку
a = "hello, word"
# и при вызове функции будет выброшено исключение
some_function(a)
except WrongTypeException as e:
print(
f"Произошла ошибка: {e.message}. Ожидается тип {e.type_name}, а в переменную {e.var_name} передан {e.real_type_name}")
# Произошла ошибка: Неверный тип!. Ожидается тип int, а в переменную value передан str
```
## Заключение
Исключения играют важную роль в обеспечении надёжности и предсказуемости программ. Класс `WrongTypeException` позволяет
разработчикам легко создавать контролируемые условия для предотвращения неправильного использования типов данных и
повышения качества ПО.
[На главную](../../index.md)

View File

@@ -0,0 +1,39 @@
# Класс `ArrayExtension`
Класс `ArrayExtension` предназначен для работы с массивами строк в Python. Главная задача класса — удаление пустых строк
из массива и возможная последующая сортировка оставшихся элементов.
## Основная информация
- **Имя файла**: anb_python_components\extensions\array_extension.py
- **Автор**: Александр Бабаев
- **Версия**: 1.0.0
- **Дата начала поддержки**: с версии 1.0
## Атрибуты и методы класса
### Метод `remove_empties`
Удаляет пустые строки из массива, дополнительно предоставляя возможность отсортировать оставшиеся элементы.
**Параметры**:
- `array`: Входной массив строк.
- `re_sort`: Флаг, определяющий необходимость сортировки результата (по умолчанию установлен в `False`).
**Пример использования**:
```python
from anb_python_components.extensions.array_extension import ArrayExtension
arr = ["apple", "", "banana", " ", ""]
clean_arr = ArrayExtension.remove_empties(arr)
print(clean_arr) # ['apple', 'banana']
```
## Заключение
Класс `ArrayExtension` полезен при очистке массивов от ненужных элементов, улучшая качество данных и повышая
эффективность дальнейшей обработки. Особенно удобен в приложениях, где важны чистота и порядок данных.
[На главную](../../index.md)

View File

@@ -14,6 +14,12 @@
- [перечисление `NotBoolAction`](class_desc/enums/not_bool_action.md)
### Исключения
**Расположение модулей**: anb_python_components\exceptions\*
- [класс-исключение `WrongTypeException`](class_desc/exceptions/wrong_type_exception.md)
### Расширения стандартных типов
**Расположение модулей**: anb_python_components\extensions\*
@@ -21,4 +27,5 @@
- [класс `StringExtensionConstants`](class_desc/extensions/string_extension_constant.md)
- [класс `StringExtension`](class_desc/extensions/string_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)

View File

@@ -0,0 +1,21 @@
# array_extension_test.py
import unittest
from anb_python_components.extensions.array_extension import ArrayExtension
class ArrayExtensionTest(unittest.TestCase):
def test_remove_empties(self):
array = ["Мама", "Папа", "", "", "он", "", "она", "вместе", "", "дружная", "", "семья", ""]
removed_empties = ["Мама", "Папа", "он", "она", "вместе", "дружная", "семья"]
sorted_removed_empties = ["Мама", "Папа", "вместе", "дружная", "он", "она", "семья"]
self.assertEqual(removed_empties, ArrayExtension.remove_empties(array))
self.assertEqual(sorted_removed_empties, ArrayExtension.remove_empties(array, True))
if __name__ == '__main__':
unittest.main()