Если вы когда-либо писали на Python и ловили себя на мысли «Опять писать парсер конфигурации…» или «Где-то у меня был код кеша, надо найти» — эта библиотека для вас.

XTools-py — это набор мощных и удобных инструментов для Python, которые помогают упростить рутинные задачи и ускорить разработку.
Вместо того чтобы тратить время на повторное изобретение велосипеда, вы получаете готовые и проверенные решения.

? Установка:

pip install xtools-py

✨ Возможности

  • Find — быстрый поиск и работа с коллекциями данных.

  • Matrix — операции с матрицами.

  • Config — удобная работа с JSON, YAML, INI.

  • Validator — валидация строк, чисел и других типов.

  • Cache — простой кеш с TTL.

  • DateTimeUtils — работа с датами и временем.

  • MathUtils — расширенные математические функции.

  • ColorUtils — преобразование и обработка цветов.

  • EncryptionUtils — шифрование и хеширование.

  • TextUtils — удобные манипуляции с текстом.

  • UnitConverter — конвертация единиц измерения.

  • AWS S3 — облачное хранилище (асинхронно/синхронно).

? Сравнение с другими библиотеками

Задача

Обычное решение

XTools-py

Работа с JSON/YAML/INI

json + pyyaml + configparser

Config — всё в одном

Валидация строк и чисел

pydantic или самописная проверка

Validator — простой API

Кеш с TTL

cachetools или functools.lru_cache

Cache — встроено

Форматирование дат

datetime + dateutil

DateTimeUtils

Конвертация цветов

Самописные функции

ColorUtils

Операции с матрицами

numpy (избыточно для простых задач)

Matrix

Шифрование и хеширование

cryptography + hashlib

EncryptionUtils

Конвертация единиц измерения

Отдельные функции

UnitConverter

Хранение файлов в облаке S3

boto3 или aioboto3

S3Storage / AsyncS3Storage

? Примеры использования

1. Работа с конфигурацией

from xtools import Config

config = Config("config.json")
config.set("app.debug", True)
config.save()

2. Быстрый поиск данных

from xtools import Find

data = ["apple", "banana", "cherry"]
print(Find.get_max(data))  # banana

3. Валидация данных

from xtools import Validator

print(Validator.is_email("test@example.com"))  # True
print(Validator.is_int("123"))                 # True

4. Кеширование

from xtools import Cache

cache = Cache()
cache.set("key", "value", ttl=60)
print(cache.get("key"))  # value

5. Работа с датами

from xtools.utils import DateTimeUtils

print(DateTimeUtils.current_timestamp())
print(DateTimeUtils.format_date("2025-02-08", "%d.%m.%Y"))

6. Конвертация единиц измерения

from xtools import UnitConverter

print(UnitConverter.celsius_to_fahrenheit(25))  # 77.0
print(UnitConverter.meters_to_kilometers(1000))  # 1.0

5. Шифрование и дешифрование

from xtools import EncryptionUtils

key = EncryptionUtils.generate_key()
encrypted = EncryptionUtils.encrypt("Hello, World!", key)
decrypted = EncryptionUtils.decrypt(encrypted, key)

print(encrypted)
print(decrypted)  # Hello, World!

8. Работа с AWS S3 (синхронно)

from xtools.storage import S3Storage

s3 = S3Storage("my-bucket", "ACCESS_KEY", "SECRET_KEY")

# Загрузка файла
s3.upload_file("local.txt", "remote.txt")

# Список файлов
print(s3.list_files())

8. Работа с AWS S3 (асинхронно)

import asyncio
from xtools.storage import AsyncS3Storage

async def main():
    s3 = AsyncS3Storage("my-bucket", "ACCESS_KEY", "SECRET_KEY")
    await s3.upload_file("local.txt", "remote.txt")
    print(await s3.list_files())

asyncio.run(main())

Подробная документация

Конфигурации

Модуль Config в XTools-py — это удобный и надёжный слой работы с конфигурационными файлами, который поддерживает JSON, YAML и INI, даёт доступ к вложенным параметрам через «dot-notation», умеет подставлять значения по умолчанию, поддерживает переопределение через переменные окружения и безопасно сохраняет файлы атомарной записью. Идея — дать единый, простой API, чтобы не подключать сразу несколько разных библиотек и не писать однотипную обвязку в каждом проекте.

Примеры использования

Файл config.yml:

app:
  debug: false
database:
  host: "localhost"
  port: 5432
  user: "app"
  password: null

Загрузка и доступ к параметрам

from xtools import Config

config = Config("config.yml", defaults={"app": {"debug": True}}, env_prefix="XT__")
print(config.get("database.host", "127.0.0.1"))  # localhost
config.set("database.password", "supersecret")
config.save()

Переопределение через переменные окружения

export XT__DATABASE__HOST=prod.db.example
export XT__APP__DEBUG=true

Перезапуск приложения — и config.update_from_env("XT__") прочитает новые значения.

Использование как контекстного менеджера

with Config("config.json", create=True) as cfg:
    cfg.set("app.version", "1.2.0")
# при выходе из with — cfg.save() выполнится автоматически

Интеграция с Validator

from xtools import Config, Validator

cfg = Config("config.yml")
port = cfg.get("database.port")
if not Validator.is_int(port):
    raise ValueError("Bad port in config")

Поиск данных

Класс Find предназначен для быстрого и удобного поиска информации в различных структурах данных. Он упрощает процесс нахождения значений в списках, словарях, вложенных структурах, а также строках. Поддерживает гибкую фильтрацию, поиск по ключам, значениям, частичное совпадение и регулярные выражения.

Работа с длинной

from XTools import Find

# Пример 1: один список чисел
print(Find.get_max([1, 3, 6]))
# Результат: {'max_number': 6}

# Пример 2: числа в виде строк
print(Find.get_max(['1', '3', '6']))
# Результат: {'max_number': 6}

# Пример 3: поиск самой длинной строки
print(Find.get_max(['hello', 'what is?', 'I using XTools']))
# Результат: {'max_len': 'I using XTools'}

# Пример 4: несколько списков
print(Find.get_max([1, 3, 6], ['hello', 'what is?', 'I using XTools']))
# Результат: {'max_number': 6, 'max_len': 'I using XTools'}

Работа с словарём

from XTools import Find

data = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
    {"name": "Charlie", "age": 25}
]

# Поиск по ключу и значению
results = Find.by_key_value(data, "age", 25)
print(results)
# Результат:
# [{'name': 'Alice', 'age': 25}, {'name': 'Charlie', 'age': 25}]

# Поиск по частичному совпадению
results = Find.contains(data, "name", "Al")
print(results)
# Результат:
# [{'name': 'Alice', 'age': 25}]

Кеширование

Класс Cache предназначен для быстрого и удобного хранения данных в памяти устройства.

Пример работы

from xtools import Cache

cache = Cache(ttl = 60, max_size = 100)
# ttl: int -> Время хранения данных (по умолчанию — 60 сек.)
# max_size: int -> Максимальный размер кэша (по умолчанию — 100 элементов).

cache.set("key", "value") # установка значений ключ = значение

print(cache.get("key"))  # value

cache.delete("key") # удаление пары по ключу

Пример с валидацией

from xtools import Cache, Validator

cache = Cache(ttl = 60, max_size = 25)
user_email = input("Enter you email > ")

if Validator.is_email(user_email):
  cache.set("user_email", user_email)

# После можно дальше в других файлах использовать кеш
user_email = cache.get("user_email")
print(f"You email: {user_email}")

Получение размера и очистка данных

from xtools import Cache

cache = Cache(ttl = 60, max_size = 25)

cache.size() # Получение длинны всего кеша

cache.clear() # Полная очистка всех данных

Работа с датами

Класс DateTimeUtils — это универсальный инструмент для упрощённой работы с датами и временем в Python. Он полностью построен на базе стандартного модуля datetime и предоставляет удобные методы, которые позволяют быстро выполнять как базовые, так и более сложные операции с датами.

Основные возможности класса:

  • Получение текущей даты и времени в разных форматах (get_now, get_today).

  • Преобразование строк в дату и обратно (parse_date, format_date).

  • Арифметика дат — добавление или вычитание дней, часов, минут (+, -)

  • Сравнение дат — сравнение, равенство между датами (==, !=, >, >=, <, <=)

  • Разница между датами — в днях, часах, секундах (diff_days, diff_seconds).

Получение даты и форматирование

from xtools.utils import DateTimeUtils


now = DateTimeUtils.current_timestamp(timezone = 'Europe/Moscow')
# timezone: str -> Вернуть дату в выбранном часовом поясе. По умолчанию - Москва (+3ч)

now_sf = DateTimeUtils.format_date(date = now, format_string = "%d.%m.%Y")
# date: datetime -> Дата в формате datetime
# format_string: str -> Формат для даты

print(now_sf) # 09.09.2025

Парсинг даты и вычисление разниц

from xtools.utils import DateTimeUtils

DateTimeUtils.parse_date(date_string = "09.08.2025", format_string = "%d.%m.%Y")

# Вычисление разниц между двумя датами в днях.

old_date = DateTimeUtils.current_timestamp() # дата устаревшая
new_date = DateTimeUtils.current_timestamp() # дата новая

res = DateTimeUtils.date_difference(old_date, now_date)

print(res) # Получаете разница между датами в днях.

Отсчёт прошеднего времени

from xtools.utils import DateTimeUtils

date = DateTimeUtils.get_now() - timedelta(hours=1)
ago = DateTimeUtils.time_ago(date) # 1 дн назад

# ИЛИ, если хотите получить в строгом формате:

ago = DateTimeUtils.time_ago(date, only_number=True) # 1_day

Аргумент only_number позволяет управлять форматом результата:

only_number=False (по умолчанию) — возвращает готовый текстовый шаблон для отображения пользователю.

Пример:

DateTimeUtils.time_ago(DateTimeUtils.get_now() - timedelta(hours=1)) # "1 ч назад"

only_number=True — возвращает строгий формат для внутренней обработки или хранения.

Пример:

DateTimeUtils.time_ago(datetime.now() - timedelta(hours=1), only_number=True)
# ➜ "1_hour"

Строгий формат, возвращаемые данные:

Тип

Означение

Примеры

justnow

Прошло меньше 60 сек. и результат будет только что(justnow)

0_justnow
13_justnow

minute

Прошло больше 60 сек, но меньше 3600 сек., тогда результат будет .. мин назад (minute)

1_minute
15_minute

hour

Прошло больше 3600 сек, но меньше 86.400 сек., тогда результат будет .. ч назад (hour)

3_hour
41_hour

day

Прошли часы и начались дни, тогда результат будет
.. дн назад (day)

3_day
29_day

month

Прошли дни и начались месяцы, тогда результат будет
.. мес назад (month)

1_month
8_month

year

Прошли месяцы и начались года, тогда результат будет
.. г назад (year)

1_year
3_year

Класс DateTime — это немного улучшенная версия библиотеки datetime.datetime. Она включает в себя небольшие удобства для работы в виде: Сохранения изменения дат, Предыдущая дата, Настоящая дата.

Пример работы:

from xtools.utils import DateTime

dt = DateTime(zone = 'Europe/Moscow') # По умолчанию зона установлена как МСК +3ч
print(dt) # результат: None
dt.now() - timedelta(hours=1)
print(dt) # результат: 2025-08-09 23:35:01.572607+03:00
dt.now()
print(dt) # результат: 2025-08-10 00:35:01.573608+03:00

# Предыдущие запросы
dt.now() - timedelta(hours=1)
dt.now()

print(dt.prev) # результат: 2025-08-09 23:35:01.572607+03:00
print(dt) # результат: 2025-08-10 00:35:01.573608+03:00

# Полный список запросов:
print(dt.results) # результат: 2025-08-10 00:35:01.573608+03:00, 
                              # 2025-08-10 00:35:01.573608+03:00

Поддерживются арифметические операции:

from xtools.utils import DateTime

dt = DateTime()
dt.now()

dt + timedelta(hours=1) # Результат: 2025-08-10 01:35:01.573608+03:00
# Идентично используя: Сложение (+) и Вычитание (-)

# Сложение двух классов
dt_a, dt_b = DateTime().now(), DateTime().now()
 
dt_a - dt_b # Результат: 0:00:00, т.к у нас одинаковые даты
# Идентично используя: Сложение (+) и Вычитание (-)

Поддерживаются сравнения и равенства:

from xtools.utils import DateTime

dt_a, dt_b = DateTime().now(), DateTime().now()

dt_a > dt_b 
dt_a < dt_b 
# Идентично используя: > | >= | <= | <

# Проверка на равенство или неравенство
dt_a == dt_b
dt_a != dt_b

# Проверка на None

dt = DateTime()
bool(dt) # Результат: False, по умолчанию результат равен None

dt = DateTime().now()
bool(dt) # Результат: True, т.к уже имеется результат

Работа с цветами

Класс ColorUtils предоставляет набор полезных методов для работы с цветами в различных форматах — HEX, RGB, HSL и др. Он упрощает преобразования между цветовыми системами, генерацию случайных цветов и их модификацию, что особенно полезно в разработке UI, графики или визуализаций данных.

С помощью ColorUtils можно:

  • Конвертировать цвета
    Перевод из HEX в RGB и обратно, а также в HSL/HSV, что удобно при работе с CSS, PIL, matplotlib или другими инструментами.

  • Генерировать случайные цвета
    Быстро создать цветовую палитру для тестирования или автоматической генерации тем оформления.

  • Менять яркость и насыщенность
    Легко осветлять или затемнять цвет, повышать или понижать его насыщенность, что упрощает создание оттенков.

  • Проверять корректность формата
    Методы для валидации введённого цвета, чтобы избежать ошибок в отрисовке.

  • Создавать градиенты
    Автоматическая генерация плавных переходов между двумя цветами в нужном количестве шагов.

Пример использования

from XTools import ColorUtils

# Конвертация HEX → RGB
print(ColorUtils.hex_to_rgb("#FF5733")) # (255, 87, 51)

# Конвертация RGB → HEX
print(ColorUtils.rgb_to_hex((255, 87, 51))) # '#FF5733'

# Генерация случайного HEX-цвета
print(ColorUtils.random_hex()) # '#3E9CFF'

# Осветление цвета на 20%
print(ColorUtils.lighten("#FF5733", 0.2)) # '#FF7A59'

# Смена насыщенности цвета
print(ColorUtils.saturate("#FF5733", 0.2)) # '#ff5732'

# Создание градиента из 5 цветов
print(ColorUtils.gradient("#FF5733", "#33FF57", steps=5))
# Результат: ['#FF5733', '#BF8044', '#80A955', '#40D266', '#33FF57']

Конвертация единиц измерения

Класс UnitConverter предоставляет возможность конвертировать физические величины: температуры, расстояния и массы. Он упрощает работу и производит преобразование благодаря физическим формулам. Все методы работают в виде @staticmethod, что позволяет не создавать экземпляр

Функционал класса

1. Конвертация температуры

  • celsius_to_fahrenheit(celsius: float) — переводит температуру из градусов Цельсия в градусы Фаренгейта.
    Формула: °F = °C × 9/5 + 32
    Пример: 25°C → 77°F

  • fahrenheit_to_celsius(fahrenheit: float) — обратное преобразование из Фаренгейта в Цельсий.
    Формула: °C = (°F - 32) × 5/9
    Пример: 77°F → 25°C

2. Конвертация расстояния

  • meters_to_kilometers(meters: float) — из метров в километры.
    Пример: 1500 м → 1.5 км

  • kilometers_to_meters(kilometers: float) — из километров в метры.
    Пример: 1.5 км → 1500 м

3. Конвертация массы

  • grams_to_kilograms(grams: float) — из граммов в килограммы.
    Пример: 2500 г → 2.5 кг

  • kilograms_to_grams(kilograms: float) — из килограммов в граммы.
    Пример: 2.5 кг → 2500 г

4. Конвертация скорости

  • kmh_to_ms(kmh: float) — перевод скорости из километров в час в метры в секунду.
    Формула: m/s = km/h ÷ 3.6
    Пример: 72 км/ч → 20 м/с

  • ms_to_kmh(ms: float) — обратное преобразование из метров в секунду в километры в час.
    Формула: km/h = m/s × 3.6
    Пример: 20 м/с → 72 км/ч

Пример использования

from XTools import UnitConverter

print(UnitConverter.celsius_to_fahrenheit(0))     # 32.0
print(UnitConverter.fahrenheit_to_celsius(32))    # 0.0
print(UnitConverter.meters_to_kilometers(1500))   # 1.5
print(UnitConverter.grams_to_kilograms(2500))     # 2.5
print(UnitConverter.kmh_to_ms(36))  # 10.0 м/с
print(UnitConverter.ms_to_kmh(10))  # 36.0 км/ч

Шифрование и Дешифрование

Класс EncryptionUtils предназначен для безопасного шифрования и дешифрования данных с использованием библиотеки cryptography.fernet. Методы работают с симметричным ключом, который обязателен как для процесса шифрования, так и для обратной операции расшифровки.

Функционал класса

1. Генерация ключа

  • generate_key() — создает новый криптографически безопасный ключ, который будет использоваться для шифрования и дешифрования данных.
    Пример:

    key = EncryptionUtils.generate_key()

2. Шифрование данных

  • encrypt(data: str, key: bytes) — принимает исходную строку и ключ, возвращает зашифрованную строку в кодировке UTF-8.
    Пример:

    encrypted = EncryptionUtils.encrypt("Hello World", key)

3. Дешифрование данных

  • decrypt(data: str, key: bytes) — принимает зашифрованную строку и ключ, возвращает исходный текст в виде строки.
    Пример:

    decrypted = EncryptionUtils.decrypt(encrypted, key)

Принцип работы

  • Используется Fernet — реализация симметричного шифрования с гарантией целостности данных.

  • Ключ генерируется один раз и должен храниться в защищенном месте (например, в переменных окружения).

  • Без правильного ключа расшифровка невозможна.

Работа с S3-хранилищами

Классы S3Storage (синхронная версия) и AsyncS3Storage (асинхронная версия) предоставляют удобный интерфейс для работы с AWS S3 и S3-совместимыми облачными хранилищами (например, MinIO, Yandex Object Storage, DigitalOcean Spaces). Они поддерживают полный набор базовых операций с файлами: загрузка, скачивание, удаление и получение списка объектов в бакете.

Возможности:

  1. Загрузка файлов

    • upload_file(file_path, s3_key) — загружает локальный файл в указанный бакет с заданным ключом (путем в хранилище).

  2. Скачивание файлов

    • download_file(s3_key, file_path) — скачивает файл из хранилища по ключу и сохраняет его локально.

  3. Удаление файлов

    • delete_file(s3_key) — удаляет объект по ключу.

  4. Список файлов

    • list_files() — возвращает список всех файлов в бакете.

Поддержка асинхронности

  • AsyncS3Storage использует aioboto3, что позволяет интегрировать работу с хранилищем в асинхронные приложения (например, FastAPI, aiohttp).

  • Синхронный S3Storage подходит для скриптов, утилит и приложений без async/await.

Пример синхронного использования

s3 = S3Storage("my-bucket", "ACCESS_KEY", "SECRET_KEY")

# Загрузка
s3.upload_file("local.txt", "folder/remote.txt")

# Скачивание
s3.download_file("folder/remote.txt", "downloaded.txt")

# Удаление
s3.delete_file("folder/remote.txt")

# Получение списка файлов
print(s3.list_files())

Пример асинхронного использования

import asyncio

async def main():
    s3 = AsyncS3Storage("my-bucket", "ACCESS_KEY", "SECRET_KEY")

    # Загрузка
    await s3.upload_file("local.txt", "folder/remote.txt")

    # Скачивание
    await s3.download_file("folder/remote.txt", "downloaded.txt")

    # Удаление
    await s3.delete_file("folder/remote.txt")

    # Список файлов
    files = await s3.list_files()
    print(files)

asyncio.run(main())

? Roadmap

  • Поддержка Redis для кеша.

  • Расширенная валидация.

  • Новые математические функции.

? Полезные ссылки

Комментарии (3)


  1. dmitriy_minaev
    13.08.2025 08:28

    Не уверен, буду ли я пользоваться этой библиотекой. Но могу накидать потенциальные идеи (не факт, что надо их делать, чисто мой опыт).
    Вот примерно такие задачи ещё часто приходится решать чем-то самописным:

    1. Конфиг в разных файлах (и иногда файлы разных форматов) и их надо слить с учетом приоретизации. В принципе, если сработает config = Config("config.yml", Config(".env")), то окей.

    2. Конфиг часто надо тестить, что указаны все нужные ключи с нужными типами (схема данных, где описаны ключи и типы).

    3. safe_get(response, ["page", 3, "cation"], "Default Caption"), когда надо вытащить response.page[3]["caption"] и не хочется проверять что есть весь путь (чтобы не падало в момент response.page[3]).

    4. менять размер кеша и ttl в процессе работы, сохранять/загружать его.

    5. Как DateTimeUtils.date_difference и операторы сравнения работают с разными часовыми поясами?

    6. Поиск внутри сложных вложенных структур, наподобе ключа словаря, который в списке словарей. Или элемент списка, который в словаре, который в списке словарей.