Asfes hackathon core library
Project description
🧠 ASFESLIB — универсальная библиотека для хакатонов и серверов ASFES
ASFESLIB — асинхронная Python-библиотека для инфраструктуры ASFES (asfes.ru).
Она объединяет всё, что нужно для быстрых серверов, API, интеграций, микросервисов, обработки данных, автоматизации и хакатонов.
⚠️ Важно: асинхронный Market API и обновлённые модули
Последние изменения:
asfeslib.utils.market_apiтеперь полностью асинхронный:safe_get,CryptoAPI,StocksAPI,ForexAPI,Market.*— вызываются только черезawait.
asfeslib.net.http.HTTPClient:- строгая проверка схем (
http:///https://), - относительные URL без
base_url→ValueError, - логи без query/fragment (не светим токены).
- строгая проверка схем (
asfeslib.core.logger.Logger:- новый аргумент
level, - нет дублирования хендлеров,
- поддержка
colorlog, аккуратный лог в файл.
- новый аргумент
asfeslib.net.mail.MailConfig:- валидатор
retry_count(1..10), rate_limit— простая защита от спама.
- валидатор
asfeslib.core.sort.async_sort:- валидирует
delay >= 0,delay < 0→ValueError.
- валидирует
- Новый пакет
asfeslib.aviation:- аэродинамика, навигация, OpenSky-клиент, мини-база аэропортов.
🚀 Основные возможности
| Модуль | Описание |
|---|---|
asfeslib.core.logger |
Цветной логгер + вывод в файл, без дублирования хендлеров |
asfeslib.core.utils |
Токены, timestamp, SHA-256, случайные строки, красивый JSON |
asfeslib.core.sort |
Набор сортировок + учебный async_sort |
asfeslib.utils.conversions |
100+ универсальных конвертаций (Length, Mass, Time, Radio, Finance, Mechanics…) |
asfeslib.utils.market_api |
Async Binance / Yahoo Finance / ER-API (кэш, ретраи, логирование) |
asfeslib.net.http |
Асинхронный HTTP-клиент с логами, retry и безопасным URL-логированием |
asfeslib.net.mail |
Асинхронная отправка писем через smtplib в asyncio + retry + rate limit |
asfeslib.databases |
Асинхронные коннекторы MongoDB, PostgreSQL, MariaDB (без логирования паролей) |
asfeslib.weather |
Полный клиент WeatherAPI (current/forecast/history/… ) |
asfeslib.aviation |
Авиационные расчёты, навигация, OpenSky-клиент, мини-база аэропортов |
📦 Установка
🔧 Режим разработчика
git clone https://github.com/alxprgs/asfeslib.git
cd asfeslib
pip install -e .
🏭 Продакшн
pip install asfeslib
🟦 1. asfeslib.core
🪵 Логгер — asfeslib.core.logger
Упрощённая обёртка над logging, безопасная к многократному созданию.
from asfeslib.core.logger import Logger
log = Logger(
name="demo",
log_to_file=True,
log_file="logs/demo.log",
level=20, # logging.INFO
)
log.info("ASFESLIB запущен!")
log.warning("Предупреждение")
log.error("Ошибка")
log.debug("Отладочная информация")
Особенности:
- Не дублирует
StreamHandler/FileHandlerпри повторном создании с тем жеname. - Если установлен
colorlog— лог в консоль будет цветным. - Параметр
log_to_file=Trueсоздаёт лог-файл с UTF-8 и простым форматированием.
Уровни можно задавать как числа logging.DEBUG / INFO / WARNING и т.д.
🧰 Утилиты — asfeslib.core.utils
from asfeslib.core import utils
utils.now_str() # "2025-11-15 13:37:00" (локальное время)
utils.gen_token(32) # безопасный hex-токен длиной 32 символа
utils.hash_text("Привет") # SHA-256 от строки (utf-8)
utils.random_string(8) # случайная a-zA-Z0-9 строка
utils.pretty_json({"a": 1, "msg": "Привет"})
Особенности:
gen_token(length: int):- гарантирует длину токена не меньше
length, - поддерживает нечётные длины (
gen_token(31)→ строка длиной 31), length <= 0→ValueError.
- гарантирует длину токена не меньше
hash_textне для паролей — только для хешей ID/логов. Для паролей нужныbcrypt/scrypt/argon2.
🔁 Сортировки — asfeslib.core.sort
from asfeslib.core import sort
import asyncio
data = [5, 3, 4, 1, 2]
print(sort.quick_sort(data))
print(sort.merge_sort(data))
print(sort.sort_builtin(data, reverse=True))
# Учебная асинхронная пузырьковая сортировка
sorted_data = asyncio.run(sort.async_sort(data, delay=0.0))
Особенности:
- Есть несколько реализаций сортировок:
bubble_sort,insertion_sort,selection_sort,merge_sort,quick_sort,heap_sort,sort_builtin. - Все поддерживают
key=иreverse=. async_sort(data, key=…, delay=0.0):- имитация сортировки с визуализацией (например, через светодиоды),
delay < 0→ValueError,delay == 0— без реальных задержек.
🟩 2. Конвертации — asfeslib.utils.conversions
Модуль содержит 100+ функций в 17 категориях:
Length— длинаMass— массаTime— времяTemperature— температураArea— площадьVolume— объёмSpeed— скоростьEnergy— энергияPressure— давлениеData— данныеAngle— углыElectricity— электричество и закон ОмаMath— проценты, средниеMechanics— сила, мощность, л.с., узлыFinance— НДС, маржа, кредитыRadio— dBm, частоты, длина волныGeophysics— давление воды, g-force и т.п.
Пример
from asfeslib.utils.conversions import Length, Radio, Finance
Length.meters_to_km(2500) # 2.5
Radio.dbm_to_mw(10) # 10.0
Finance.loan_monthly_payment(
principal=1_000_000,
annual_rate_percent=12.0,
years=20,
)
Авто-инспекция API
from asfeslib.utils.conversions import list_categories, list_functions
print(list_categories()) # ['length', 'mass', 'time', ...]
print(list_functions("length")) # ['meters_to_km', 'km_to_meters', ...]
🟧 3. Market API (async) — asfeslib.utils.market_api
Единый асинхронный API для:
- криптовалют (Binance),
- акций/ETF (Yahoo Finance),
- валют (ER-API).
⚠️ Всё
awaitable:safe_get,CryptoAPI,StocksAPI,ForexAPI,Market.*.
Быстрый пример
import asyncio
from asfeslib.utils.market_api import Market
async def main():
btc = await Market.crypto_price("BTCUSDT")
aapl = await Market.stock_price("AAPL")
eur_usd = await Market.forex_rate("EUR", "USD")
print("BTCUSDT:", btc)
print("AAPL:", aapl)
print("EUR/USD:", eur_usd)
asyncio.run(main())
OHLC
import asyncio
from asfeslib.utils.market_api import Market
async def main():
candles = await Market.crypto_ohlc("BTCUSDT", interval="1h", limit=50)
first = candles[0]
print(first["open_time"], first["open"], first["close"])
asyncio.run(main())
Особенности:
- Внутренний кэш (TTL, отключается
use_cache=Falseилиcache_ttl <= 0). - Ретраи с задержкой.
- Безопасный лог: URL в ошибках обрезается до
scheme://host/path(без query/fragment), чтобы не светить токены. - Явные исключения:
APIError— общие ошибки API/сети/формата,NotFoundError— тикер/валюта не найдены.
🟦 4. HTTP-клиент — asfeslib.net.http
Асинхронный HTTP-клиент на базе aiohttp.
import asyncio
from asfeslib.net.http import HTTPClient
async def main():
async with HTTPClient("https://api.github.com") as http:
repo = await http.get("/repos/alxprgs/asfeslib")
print(repo["full_name"])
asyncio.run(main())
Особенности:
- Поддерживаются только схемы
http://иhttps://. - Относительный URL без
base_url→ValueError. - Любая другая схема (
file://,ftp://и т.п.) →ValueError. - Авто-разбор ответа:
application/json→dict/list,text/*→str,- остальное →
bytes.
- Ретраи с backoff.
- Логирование через
logging.getLogger(__name__):- в логах URL всегда без query/fragment (
?token=...и#fragне выводятся).
- в логах URL всегда без query/fragment (
Если нужно цветное логирование, можно сконфигурировать logging через Logger из asfeslib.core.logger.
🟨 5. SMTP-почта — asfeslib.net.mail
Асинхронная обёртка над стандартным smtplib, запускаемым через asyncio.to_thread.
Особенности:
- SSL / TLS,
- несколько попыток (
retry_count,retry_delay), - простая защита от спама —
rate_limit(минимальный интервал между отправками), - вложения,
- удобные Pydantic-модели:
MailConfig,MailMessage,MailAttachment.
Пример
import asyncio
from asfeslib.net.mail import MailConfig, MailMessage, MailClient
cfg = MailConfig(
host="mail.asfes.ru",
port=465,
username="hackathon@asfes.ru",
password="***",
from_name="ASFES Mailer",
retry_count=3,
retry_delay=1.0,
rate_limit=0.0,
)
msg = MailMessage(
to=["admin@asfes.ru"],
subject="ASFESLIB test",
body="Если ты читаешь это письмо — SMTP работает!",
html=False,
)
async def main():
async with MailClient(cfg) as mail:
ok = await mail.send(msg, log=True)
print("Sent:", ok)
asyncio.run(main())
⚠️
retry_countвалидируется Pydantic: 1..10, иначеValueError.
🗃 6. Базы данных — asfeslib.databases
Поддерживаются:
- MongoDB (
motor), - PostgreSQL (
psycopg[async]), - MariaDB/MySQL (
aiomysql).
Основные функции:
asfeslib.databases.MongoDB.connect_mongoasfeslib.databases.PostgreSQL.connect_postgresasfeslib.databases.MySQL.connect_mariadb- агрегатор
asfeslib.databases.connect_database
Пример MongoDB
import asyncio
from asfeslib.databases.MongoDB import MongoConnectScheme, connect_mongo
cfg = MongoConnectScheme(
host="mongodb.asfes.ru",
port=27017,
username="user",
password="password",
db_name="hackathon_db",
)
async def main():
client, db, ok = await connect_mongo(cfg)
print("Mongo status:", ok)
asyncio.run(main())
Особенности:
- URL-ы собираются с учётом спецсимволов (
quote_plusдля логина/пароля). - Для логирования используются «безопасные» описания (
host:port/db), пароль в логах никогда не светится. - Есть
serverSelectionTimeoutMS/connect_timeout, чтобы не висеть вечно.
Агрегатор — connect_database
from asfeslib.databases import connect_database
from asfeslib.databases.MongoDB import MongoConnectScheme
cfg = MongoConnectScheme(db_name="hackathon_db")
client, db_or_conn, ok = await connect_database("mongo", cfg)
🌦 7. WeatherAPI — asfeslib.weather
Полный клиент WeatherAPI:
current— текущая погода,forecast— прогноз,history— исторические данные,future,astronomy,alerts,marine,bulk,ip/timezoneи т.д.
Пример
import asyncio
from asfeslib.weather import WeatherApiClient
async def main():
async with WeatherApiClient(api_key="YOUR_WEATHERAPI_KEY") as w:
resp = await w.current("Moscow")
print(resp.location.name, resp.current.temp_c)
asyncio.run(main())
Особенности:
- Ленивый
httpx.AsyncClient— создаётся только при первом запросе. - Внутренние
_get/_postс аккуратной типизацией. - Все конечные методы возвращают Pydantic-модели (
CurrentResponse,ForecastResponse,AlertsResponseи т.п.).
✈️ 8. Aviation — asfeslib.aviation
Набор утилит для авиационных задач:
aero— атмосфера ISA, число Маха, подъёмная сила, скорость сваливания, fuel planning.nav— Haversine-расстояние, курсы, точка назначения, ETA, ветровые поправки.api— асинхронный клиент OpenSky Network (live-трафик самолётов).data— мини-база аэропортов (несколько популярных в мире).
Базовые расчёты
from asfeslib.aviation import (
air_density_isa,
speed_of_sound,
mach_to_kmh,
kmh_to_mach,
stall_speed,
)
rho0 = air_density_isa(0) # ≈ 1.225 кг/м³
a0 = speed_of_sound(0) # ≈ 340 м/с
m = kmh_to_mach(900, altitude_m=11000)
vs = stall_speed(
weight_kg=70000,
wing_area_m2=122,
cl_max=2.0,
altitude_m=0,
)
Навигация
from asfeslib.aviation import (
haversine_distance_km,
initial_bearing_deg,
destination_point,
eta_hours,
wind_corrected_heading,
)
d = haversine_distance_km(55.75, 37.61, 59.93, 30.33) # Москва – СПб
bearing = initial_bearing_deg(55.75, 37.61, 59.93, 30.33)
lat2, lon2 = destination_point(55.0, 37.0, bearing_deg=45, distance_km=100)
eta = eta_hours(distance_km=d, ground_speed_kmh=800)
heading, gs = wind_corrected_heading(
course_deg=90,
tas_kts=120,
wind_dir_from_deg=0,
wind_speed_kts=20,
)
Аэропорты
from asfeslib.aviation import get_airport, airport_coords, runway_length_m
ap = get_airport("UUDD") # ICAO или IATA (DME)
coords = airport_coords("DME")
rw_len = runway_length_m("UUEE")
OpenSky клиент
import asyncio
from asfeslib.aviation import OpenSkyClient
async def main():
async with OpenSkyClient() as sky:
data = await sky.live_area(
min_lat=54.0, min_lon=35.0,
max_lat=57.0, max_lon=39.0, # район Москвы
)
print("Бортов в зоне:", len(data))
asyncio.run(main())
⚠️ OpenSky API публичный, без ключа, но с лимитами.
При превышении лимита может прилететь 429 — в live-тестах это корректно обрабатывается какskip.
🧪 Тесты и live-режим
Все основные модули покрыты тестами pytest.
Обычные тесты
pytest
Live-тесты
Live-тесты по умолчанию отключены, включаются маркером live:
pytest -m live
Используются:
tests/test_mail_live.pytests/test_market_live.pytests/test_weather_live_api.pytests/test_aviation_live.py
Часть из них требует переменных окружения:
# PowerShell пример
$env:ASFESLIB_SMTP_USER = "hackathon@asfes.ru"
$env:ASFESLIB_SMTP_PASSWORD = "SMTP_PASSWORD"
$env:ASFESLIB_WEATHER_API_KEY = "YOUR_WEATHERAPI_KEY"
Часть тестов может быть скипнута:
- Yahoo Finance / OpenSky → при
HTTP 429(rate limit). - WeatherAPI → если нет
ASFESLIB_WEATHER_API_KEY.
📂 Структура проекта
asfeslib/
│
├── core/
│ ├── logger.py
│ ├── utils.py
│ └── sort.py
│
├── utils/
│ ├── conversions.py
│ └── market_api.py
│
├── databases/
│ ├── MongoDB.py
│ ├── MySQL.py
│ ├── PostgreSQL.py
│ └── __init__.py
│
├── net/
│ ├── http.py
│ └── mail.py
│
├── weather/
│ ├── client.py
│ ├── models/
│ └── ...
│
├── aviation/
│ ├── __init__.py
│ ├── aero.py
│ ├── nav.py
│ ├── api.py
│ └── data.py
│
└── tests/
🛠 Использование в FastAPI
Пример подключения БД и логгера в FastAPI-приложении:
from fastapi import FastAPI
from asfeslib.core.logger import Logger
from asfeslib.databases import connect_database
from asfeslib.databases.MongoDB import MongoConnectScheme
log = Logger("api")
app = FastAPI()
@app.on_event("startup")
async def startup():
cfg = MongoConnectScheme(db_name="hackathon_db")
client, app.state.db, ok = await connect_database("mongo", cfg)
if ok:
log.info("MongoDB подключена!")
else:
log.error("Не удалось подключиться к MongoDB")
📜 Лицензия
MIT License
👤 Контакты
- 🌐 https://asfes.ru/
- 🔧 GitHub: https://github.com/alxprgs/
- ✉️ Автор: Александр
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asfeslib-0.3.1.tar.gz.
File metadata
- Download URL: asfeslib-0.3.1.tar.gz
- Upload date:
- Size: 72.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a42fb106a6fd254a1046b3d39138ebcb8e4b84d131a28fbeeec0e5a35ec83f3d
|
|
| MD5 |
b820564de3085a65a3931eb3b666a233
|
|
| BLAKE2b-256 |
b5bbd8abf658a3bab089af8152fce5acd59f1a86284285fbe2eede6042c79e19
|
File details
Details for the file asfeslib-0.3.1-py3-none-any.whl.
File metadata
- Download URL: asfeslib-0.3.1-py3-none-any.whl
- Upload date:
- Size: 62.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c64656aef54d8a98af3cf1fc26c269a3088b4d239c6ae5aada61616f46bb6a7
|
|
| MD5 |
c8a57d5760c461385a6ee3e450891db8
|
|
| BLAKE2b-256 |
9ba961edaf73a5491a860f26ecaeda33f50d6d07cf728a0a1703f1ae8c115ae0
|