diff --git a/.run/Тест ArrayExtension.run.xml b/.run/Тест ArrayExtension.run.xml new file mode 100644 index 0000000..c46e033 --- /dev/null +++ b/.run/Тест ArrayExtension.run.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/.run/Тест TypeExtension.run.xml b/.run/Тест TypeExtension.run.xml new file mode 100644 index 0000000..788bee3 --- /dev/null +++ b/.run/Тест TypeExtension.run.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/anb_python_components/classes/__init__.py b/anb_python_components/classes/__init__.py new file mode 100644 index 0000000..6ef5cd0 --- /dev/null +++ b/anb_python_components/classes/__init__.py @@ -0,0 +1 @@ +# anb_python_components/classes/__init__.py \ No newline at end of file diff --git a/anb_python_components/classes/guid.py b/anb_python_components/classes/guid.py new file mode 100644 index 0000000..ea257d0 --- /dev/null +++ b/anb_python_components/classes/guid.py @@ -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)) diff --git a/anb_python_components/exceptions/__init__.py b/anb_python_components/exceptions/__init__.py new file mode 100644 index 0000000..5c7dafc --- /dev/null +++ b/anb_python_components/exceptions/__init__.py @@ -0,0 +1 @@ +# anb_python_components/exceptions/__init__.py \ No newline at end of file diff --git a/anb_python_components/exceptions/wrong_type_exception.py b/anb_python_components/exceptions/wrong_type_exception.py new file mode 100644 index 0000000..fca3dc9 --- /dev/null +++ b/anb_python_components/exceptions/wrong_type_exception.py @@ -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 diff --git a/anb_python_components/extensions/array_extension.py b/anb_python_components/extensions/array_extension.py new file mode 100644 index 0000000..482aff7 --- /dev/null +++ b/anb_python_components/extensions/array_extension.py @@ -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 diff --git a/anb_python_components/extensions/guid_extension.py b/anb_python_components/extensions/guid_extension.py new file mode 100644 index 0000000..0aed92b --- /dev/null +++ b/anb_python_components/extensions/guid_extension.py @@ -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.') diff --git a/help/class_desc/exceptions/wrong_type_exception.md b/help/class_desc/exceptions/wrong_type_exception.md new file mode 100644 index 0000000..1f8befe --- /dev/null +++ b/help/class_desc/exceptions/wrong_type_exception.md @@ -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) \ No newline at end of file diff --git a/help/class_desc/extensions/array_extension.md b/help/class_desc/extensions/array_extension.md new file mode 100644 index 0000000..f3c07d0 --- /dev/null +++ b/help/class_desc/extensions/array_extension.md @@ -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) \ No newline at end of file diff --git a/help/index.md b/help/index.md index a5bdb99..464d54c 100644 --- a/help/index.md +++ b/help/index.md @@ -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) \ No newline at end of file +- [класс `TypeExtension`](class_desc/extensions/type_extension.md) +- [класс `ArrayExtension`](class_desc/extensions/array_extension.md) \ No newline at end of file diff --git a/tests/extensions/array_extension_test.py b/tests/extensions/array_extension_test.py new file mode 100644 index 0000000..b530adc --- /dev/null +++ b/tests/extensions/array_extension_test.py @@ -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()