mnemosynecore
mnemosynecore — Python-библиотека для аналитиков и data-инженеров.
Главная идея: писать меньше служебного кода в DAG/ноутбуках и быстрее решать рабочие задачи:
- достать секреты и подключения,
- выполнить SQL в Vertica,
- отправить отчёт в Mattermost,
- сделать скриншот Superset,
- быстро обратиться к LLM через один вызов,
- скачать файл из SharePoint,
- добавить надёжные retry.
Зачем это аналитикам
Эта библиотека убирает рутину:
- не нужно каждый раз вручную писать код авторизации,
- одинаковый подход в проде и локально,
- проще проверять логику до выкладки в Airflow,
- меньше копипаста между задачами команды.
Установка
pip install mnemosynecore
Опциональные зависимости:
# Airflow helpers
pip install "mnemosynecore[airflow]"
# Superset API
pip install "mnemosynecore[superset]"
# SharePoint NTLM
pip install "mnemosynecore[sharepoint]"
# ClickHouse через un_conn
pip install "mnemosynecore[clickhouse]"
# Визуализация (PNG графики)
pip install "mnemosynecore[viz]"
# Всё вместе
pip install "mnemosynecore[airflow,superset,sharepoint,clickhouse,viz]"
Быстрый старт (2 минуты)
import mnemosynecore as mn
# 1) взять секрет
cfg = mn.get_secret("VERTICA_PROD")
print(cfg["host"])
# 2) выполнить SQL
df = mn.vertica_select(
conn_id="VERTICA_PROD",
sql="SELECT CURRENT_DATE AS dt",
)
print(df)
Готовые скрипты с рабочими примерами лежат в папке examples/:
examples/01_secrets_and_test_mode.pyexamples/02_vertica_examples.pyexamples/03_mattermost_examples.pyexamples/04_superset_examples.pyexamples/05_sharepoint_examples.pyexamples/06_superset_links_and_threads.pyexamples/07_llm_examples.pyexamples/08_mattermost_emoji_letters.pyexamples/09_reporting_examples.pyexamples/10_viz_examples.py
Обычные функции и _test-функции
Почти для всех интеграционных функций есть пара:
- обычная: работает с ENV/Vault/Airflow,
_test: для локального запуска с JSON-кредами.
Пример пары:
vertica_select(...)vertica_select_test(..., dir_path=... | creds_path=...)
Как передавать креды локально
Есть 2 способа:
dir_path— путь к папке, где лежит<CONN_ID>.jsoncreds_path— прямой путь к файлу JSON
Пример:
# Файл: ./local_secrets/VERTICA_DEV.json
df = mn.vertica_select_test(
conn_id="VERTICA_DEV",
sql="SELECT 1",
dir_path="./local_secrets",
)
# Файл: /Users/me/secrets/vertica_dev.json
df = mn.vertica_select_test(
conn_id="VERTICA_DEV",
sql="SELECT 1",
creds_path="/Users/me/secrets/vertica_dev.json",
)
Формат JSON-кредов
Универсальный формат:
{
"host": "example.host",
"login": "user",
"password": "secret",
"port": 443,
"schema": "https",
"extra": "{\"basepath\":\"/api/v4\"}"
}
Mattermost
{
"host": "mattermost.company.ru",
"password": "BOT_TOKEN",
"schema": "https",
"port": 443,
"extra": "{\"basepath\":\"/api/v4\"}"
}
Можно использовать не только бот-токен, но и личный user-token:
- передайте его в
password(JSON/секрет), - сообщение будет отправлено от имени владельца этого токена.
Superset
{
"host": "https://ss.company.ru",
"login": "svc_user",
"password": "svc_password",
"extra": "{\"auth_provider\":\"ldap\"}"
}
LLM (OpenAI-compatible gateway/API)
{
"host": "http://llm-gateway.prod.a.o3.ru/api",
"password": "LLM_TOKEN",
"model": "DeepSeek-V3-0324-AWQ[CM]",
"extra": "{\"endpoint\":\"/chat/completions\"}"
}
Для Vertica/коннектов можно указывать и login, и user:
- если есть
user, библиотека использует его, - если
userнет, беретсяlogin.
SharePoint
{
"host": "https://sharepoint.company.ru",
"login": "svc_sharepoint",
"password": "svc_password",
"schema": "O3"
}
Примеры: секреты и подключения
import mnemosynecore as mn
# Прод: ENV/Vault/Airflow
secret = mn.get_secret("MM_BOT")
# Локально: из JSON
secret_test = mn.get_secret_test("MM_BOT", dir_path="./secrets")
secret_test2 = mn.get_secret_test("MM_BOT", creds_path="./secrets/mm_bot.json")
# Универсально: сначала локально, если не нашли — прод
cfg = mn.resolve_secret("MM_BOT", dir_path="./secrets")
# Проверка обязательных полей
mn.require_secret_fields("MM_BOT", ["host", "password"])
Примеры: Vertica
import pandas as pd
import mnemosynecore as mn
# 1) SELECT
sales_df = mn.vertica_select(
conn_id="VERTICA_PROD",
sql="""
SELECT dt, revenue
FROM mart.daily_sales
WHERE dt >= CURRENT_DATE - INTERVAL '7 day'
""",
)
# 2) Scalar
row_count = mn.vertica_select_scalar(
conn_id="VERTICA_PROD",
sql="SELECT COUNT(*) FROM mart.daily_sales",
)
# 3) Выполнить SQL из файла
mn.vertica_sql_file(
file_path="./sql/rebuild_mart.sql",
conn_id="VERTICA_PROD",
)
# 4) Upsert из DataFrame
new_rows = pd.DataFrame([
{"id": 1, "dt": "2026-03-01", "revenue": 10.0},
{"id": 2, "dt": "2026-03-01", "revenue": 20.0},
])
mn.vertica_upsert(
df=new_rows,
table_name="mart.daily_sales",
unique_keys=["id", "dt"],
conn_id="VERTICA_PROD",
)
# 5) Локальный тест через JSON
test_df = mn.vertica_select_test(
conn_id="VERTICA_DEV",
sql="SELECT 1 AS x",
dir_path="./secrets",
)
Примеры: Mattermost
import pandas as pd
import mnemosynecore as mn
# Текстовое сообщение
mn.send_message(
channel_id="channel_id_here",
bot_id="MM_BOT",
text="Ежедневный отчёт готов",
)
# Короткий алиас (то же самое)
mn.send_text(
channel_id="channel_id_here",
bot_id="MM_BOT",
text="Ежедневный отчёт готов",
)
# Файл
mn.send_file(
channel_id="channel_id_here",
bot_id="MM_BOT",
file_path="./reports/daily_sales.xlsx",
text="Отчёт во вложении",
)
# DataFrame как CSV
df = pd.DataFrame([{"country": "RU", "value": 100}])
mn.send_dataframe_as_csv(
channel_id="channel_id_here",
bot_id="MM_BOT",
df=df,
file_name="daily_metrics.csv",
)
# Локально (_test) с creds_path
mn.send_message_test(
channel_id="channel_id_here",
bot_id="MM_BOT",
text="Проверка локальной отправки",
creds_path="./secrets/mm_bot.json",
)
# Ответ в тред обычным текстом
mn.send_thread_message(
channel_id="channel_id_here",
bot_id="MM_BOT",
root_id="post_id_основного_сообщения",
text="Дополнительный комментарий в тред",
)
# Короткий алиас для ответа в тред
mn.reply_text(
channel_id="channel_id_here",
bot_id="MM_BOT",
root_id="post_id_основного_сообщения",
text="Ещё один комментарий в тред",
)
# Можно и файл/таблицу отправить прямо в тред через root_id
mn.send_dataframe_as_csv(
channel_id="channel_id_here",
bot_id="MM_BOT",
root_id="post_id_основного_сообщения",
df=df,
file_name="details.csv",
)
# Текст "буквенными" emoji:
# "tipa takogo" -> :t_letter: :i_letter: :p_letter: ...
mn.send_message_as_letter_emojis(
channel_id="channel_id_here",
bot_id="MM_BOT_OR_PERSONAL_TOKEN_CONN",
text="tipa takogo",
)
# Поставить реакции-буквы к посту (слово из реакций)
mn.add_letter_emoji_reactions(
post_id="post_id_here",
bot_id="MM_BOT_OR_PERSONAL_TOKEN_CONN",
text="ok",
)
# Важно: одинаковую реакцию один пользователь обычно не может поставить дважды.
# Поэтому для слов с повторяющимися буквами повторы по умолчанию пропускаются.
Примеры: Superset
import mnemosynecore as mn
# Скриншот дашборда (bytes)
png = mn.superset_dashboard_thumbnail(
superset_conn="SUPERSET_CONN",
dashboard_name="Финансы - ежедневный обзор",
)
# Отправить скриншот дашборда в Mattermost
mn.send_superset_dashboard_screenshot(
channel_id="channel_id_here",
bot_id="MM_BOT",
superset_conn="SUPERSET_CONN",
dashboard_name="Финансы - ежедневный обзор",
text="Скриншот утреннего дашборда",
)
# Локально (_test) с JSON кредами
mn.superset_chart_thumbnail_test(
superset_conn="SUPERSET_CONN",
chart_id=31729,
creds_path="./secrets/superset_conn.json",
)
# Ссылка на дашборд (markdown)
dash_link = mn.superset_dashboard_link(
superset_conn="SUPERSET_CONN",
dashboard_id=145,
dashboard_name="Daily KPI",
)
# Отправка только ссылки в канал
mn.send_superset_dashboard_link(
channel_id="channel_id_here",
bot_id="MM_BOT",
superset_conn="SUPERSET_CONN",
dashboard_id=145,
dashboard_name="Daily KPI",
text="Отчёт на сегодня",
)
# Ссылки на дашборды в тред + обычные текстовые сообщения в этом же треде
mn.send_superset_dashboard_links_to_thread(
channel_id="channel_id_here",
bot_id="MM_BOT",
superset_conn="SUPERSET_CONN",
dashboards=[
{"dashboard_name": "Main", "id": 145},
{"dashboard_name": "Finance", "id": 146},
],
header_text="Ежедневная подборка дашбордов",
thread_messages=[
"Если график выглядит странно, пишите в этот тред.",
"Детали по фильтрам приложу чуть позже.",
],
)
# Сохранить скриншот в конкретный файл
mn.superset_dashboard_screenshot_to_file(
superset_conn="SUPERSET_CONN",
dashboard_id=145,
output_path="./tmp/daily_kpi_dashboard.png",
)
# Новый быстрый сценарий:
# взяли permalink из UI Superset (с фильтрами) и отправили скрин + ссылку
mn.send_superset_dashboard_permalink_screenshot(
channel_id="channel_id_here",
bot_id="MM_BOT",
superset_conn="SUPERSET_CONN",
dashboard_name="Daily KPI (filtered)",
dashboard_url="https://ss.company.ru/superset/dashboard/p/AbCdEf123/?native_filters_key=...",
text="Борд с применёнными фильтрами из UI",
)
Примеры: LLM
import mnemosynecore as mn
# 1) Самый быстрый вариант: token + model + prompt параметрами
answer = mn.llm_chat(
prompt="Сделай 3 пункта summary по таблице заказов",
model="gpt-4o-mini",
token="your_token_here",
base_url="https://api.openai.com/v1",
)
print(answer)
# 2) Токен из файла (txt/json)
answer2 = mn.llm_chat(
prompt="Объясни разницу между DAU и MAU в 2 предложениях",
model="DeepSeek-V3-0324-AWQ[CM]",
token_path="./secrets/llm_token.txt",
base_url="http://llm-gateway.prod.a.o3.ru/api",
)
# 3) Через Vault/ENV/Airflow по conn_id (host/token/model в секрете)
answer3 = mn.llm_chat(
prompt="Сгенерируй чек-лист проверки витрины перед релизом",
llm_conn="LLM_GATEWAY",
)
# 4) Локально (_test): указать прямой путь к файлу с кредами
answer4 = mn.llm_chat_test(
prompt="Верни JSON: {\"ok\": true}",
llm_conn="LLM_GATEWAY",
creds_path="./secrets/LLM_GATEWAY.json",
parse_json=True,
)
print(answer4) # {'ok': True}
Примеры: Reporting utilities
import pandas as pd
import mnemosynecore as mn
# 1) SQL -> preview + CSV в Mattermost за один вызов
mn.send_query_report(
channel_id="channel_id_here",
bot_id="MM_BOT",
conn_id="VERTICA_PROD",
sql="SELECT * FROM mart.kpi_daily WHERE dt = CURRENT_DATE - 1",
header_text="KPI за вчера",
)
# 2) KPI current vs previous
mn.send_kpi_report(
channel_id="channel_id_here",
bot_id="MM_BOT",
conn_id="VERTICA_PROD",
current_sql="SELECT metric, value FROM mart.kpi_current",
previous_sql="SELECT metric, value FROM mart.kpi_previous",
)
# 3) Data quality report
df = pd.DataFrame([
{"id": 1, "value": 10, "dt": "2026-03-01"},
{"id": 1, "value": 10, "dt": "2026-03-01"},
{"id": 2, "value": None, "dt": "2026-03-02"},
])
dq = mn.data_quality_report(df=df, freshness_col="dt")
print(mn.format_data_quality_report(dq))
mn.send_data_quality_report(
channel_id="channel_id_here",
bot_id="MM_BOT",
df=df,
freshness_col="dt",
)
# 4) SharePoint файл -> Vertica
mn.sharepoint_to_vertica(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/input/kpi.csv",
table_name="stg.kpi_input",
vertica_conn_id="VERTICA_PROD",
mode="upsert",
unique_keys=["id"],
)
Примеры: Визуализация
import pandas as pd
import mnemosynecore as mn
df = pd.DataFrame([
{"dt": "2026-03-01", "revenue": 100, "orders": 10},
{"dt": "2026-03-02", "revenue": 120, "orders": 12},
{"dt": "2026-03-03", "revenue": 90, "orders": 9},
])
line_png = mn.plot_line_png(df=df, x="dt", y=["revenue", "orders"], title="Revenue and Orders")
bar_png = mn.plot_bar_png(df=df, x="dt", y="revenue", title="Revenue by day")
heat_png = mn.plot_heatmap_png(df=df[["revenue", "orders"]], title="Heatmap")
mn.send_plot(
channel_id="channel_id_here",
bot_id="MM_BOT",
png_bytes=line_png,
file_name="line.png",
text="Линейный график",
)
Примеры: SharePoint
import mnemosynecore as mn
# Скачать файл в память
content = mn.sharepoint_download_file(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/reports/plan.csv",
)
# Прочитать CSV сразу в DataFrame
df = mn.sharepoint_read_csv(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/reports/plan.csv",
)
# Сохранить файл локально
mn.sharepoint_download_to_file(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/reports/plan.csv",
output_path="./tmp/plan.csv",
)
# Локально (_test)
df_local = mn.sharepoint_read_csv_test(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/reports/plan.csv",
dir_path="./secrets",
)
Примеры готовых сценариев для аналитика
Сценарий 1: загрузить данные из SharePoint и отправить summary в Mattermost
import mnemosynecore as mn
df = mn.sharepoint_read_csv(
sharepoint_conn="SP_CONN",
file_url="/sites/analytics/input/sales.csv",
)
summary = df.groupby("country", as_index=False)["amount"].sum()
mn.send_dataframe_preview(
channel_id="channel_id_here",
bot_id="MM_BOT",
df=summary,
title="Сумма продаж по странам",
)
Сценарий 2: выполнить SQL и отправить CSV в Mattermost
import mnemosynecore as mn
df = mn.vertica_select(
conn_id="VERTICA_PROD",
sql="SELECT * FROM mart.kpi_daily WHERE dt = CURRENT_DATE - 1",
)
mn.send_dataframe_as_csv(
channel_id="channel_id_here",
bot_id="MM_BOT",
df=df,
file_name="kpi_daily.csv",
text="KPI за вчера",
)
Сценарий 3: nightly-скриншоты Superset в разные каналы
import mnemosynecore as mn
mn.send_superset_dashboards_to_channels(
bot_id="MM_BOT",
superset_conn="SUPERSET_CONN",
dashboards=[
{
"dashboard_name": "Продажи - общий",
"channel_id": "sales_channel",
"text": "Утренний срез",
},
{
"dashboard_name": "Логистика - SLA",
"channel_id": "ops_channel",
"text": "SLA на утро",
},
],
)
Основные группы API
Секреты
get_connection_as_json,get_connection_as_json_testget_secret,get_secret_testresolve_secret,resolve_secret_testhas_connection,get_secret_field,require_secret_fields,get_secret_with_defaults
Vertica
vertica_conn,vertica_conn_testvertica_sql,vertica_sql_testvertica_select,vertica_select_testvertica_select_scalar,vertica_select_scalar_testvertica_insert_dataframe,vertica_insert_dataframe_testvertica_sql_file,vertica_sql_file_testvertica_sql_dir,vertica_sql_dir_testvertica_dedupe,vertica_dedupe_testvertica_upsert,vertica_upsert_test
Mattermost
post_message,post_message_testsend_message,send_message_testsend_text,send_text_test(короткие алиасы)send_thread_message,send_thread_message_testreply_text,reply_text_test(короткие алиасы)send_thread_messages,send_thread_messages_testsend_file,send_file_testsend_file_bytes,send_file_bytes_testsend_files,send_files_testsend_dataframe_as_csv,send_dataframe_as_csv_testsend_dataframe_preview,send_dataframe_preview_testtext_to_letter_emojissend_message_as_letter_emojis,send_message_as_letter_emojis_testadd_letter_emoji_reactions,add_letter_emoji_reactions_test
Superset
get_superset_client,get_superset_client_testsuperset_request,superset_request_testsuperset_dashboard_url,superset_dashboard_url_testsuperset_chart_url,superset_chart_url_testsuperset_dashboard_link,superset_dashboard_link_testsuperset_chart_link,superset_chart_link_testsuperset_dashboard_thumbnail,superset_dashboard_thumbnail_testsuperset_chart_thumbnail,superset_chart_thumbnail_testsuperset_dashboard_screenshot_to_file,superset_dashboard_screenshot_to_file_testsuperset_chart_screenshot_to_file,superset_chart_screenshot_to_file_testsuperset_screenshot_dashboard,superset_screenshot_dashboard_testsuperset_screenshot_charts,superset_screenshot_charts_testsend_superset_dashboard_screenshot,send_superset_dashboard_screenshot_testsend_superset_dashboard_permalink_screenshot,send_superset_dashboard_permalink_screenshot_testsend_superset_chart_screenshot,send_superset_chart_screenshot_testsend_superset_dashboard_link,send_superset_dashboard_link_testsend_superset_chart_link,send_superset_chart_link_testsend_superset_dashboard_links_to_thread,send_superset_dashboard_links_to_thread_testsend_superset_chart_links_to_thread,send_superset_chart_links_to_thread_testsend_superset_dashboards_to_channels,send_superset_dashboards_to_channels_testsend_superset_charts_to_channels,send_superset_charts_to_channels_test
SharePoint
sharepoint_download_file,sharepoint_download_file_testsharepoint_download_to_file,sharepoint_download_to_file_testsharepoint_read_text,sharepoint_read_text_testsharepoint_read_dataframe,sharepoint_read_dataframe_testsharepoint_read_csv,sharepoint_read_csv_testsharepoint_read_excel,sharepoint_read_excel_testsharepoint_read_json,sharepoint_read_json_testsharepoint_read_sql,sharepoint_read_sql_testsharepoint_download_many,sharepoint_download_many_test
Reporting
send_query_report,send_query_report_testsend_kpi_report,send_kpi_report_testdata_quality_reportformat_data_quality_reportsend_data_quality_report,send_data_quality_report_testsharepoint_to_vertica,sharepoint_to_vertica_test
LLM
llm_chat,llm_chat_testllm_summarize_dataframe,llm_summarize_dataframe_testllm_explain_kpi_delta,llm_explain_kpi_delta_testllm_write_mattermost_update,llm_write_mattermost_update_testllm_classify_texts,llm_classify_texts_test
Визуализация
plot_line_pngplot_bar_pngplot_heatmap_pngsend_plot,send_plot_test
Retry
retry_call,retry
Локальная проверка перед релизом
pytest -q
Релиз и публикация
В проекте есть скрипт release.sh:
- повышает версию,
- запускает тесты,
- собирает пакет,
- публикует в TestPyPI/PyPI,
- делает commit/push.
Примеры:
# Только TestPyPI
./release.sh --target testpypi
# TestPyPI + PyPI
./release.sh --target both
# Явно задать версию
./release.sh --version 1.2.0 --target both
Для публикации нужен токен Twine (~/.pypirc или переменные TWINE_*).
Metadata
Release files for mnemosynecore 1.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mnemosynecore-1.1.8.tar.gz | 58.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mnemosynecore-1.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.6 kB
Release files / mnemosynecore-1.1.8.tar.gz
| Download URL | mnemosynecore-1.1.8.tar.gz |
|---|---|
| Size | 58.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
703a24a210423b4baf1046c088907b56d084004ba79513db9188afb7e93be9e1
|
|
BLAKE2b-256 checksum How to use checksums |
a8e1477740bf49aef0c20d826d552a8052dbb98fb760ce02e14054ef1e016dcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|
Release files / mnemosynecore-1.1.8-py3-none-any.whl
| Download URL | mnemosynecore-1.1.8-py3-none-any.whl |
|---|---|
| Size | 43.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1c2f5d9aa79e9f4b2d56cc3d9aa757b317466146877c0be39536c6a5e1a1ede
|
|
BLAKE2b-256 checksum How to use checksums |
35fee6e48486159ca5d49674d89e2b066f4aaf023cd24b05969ba06c59deef39
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|