From 5761400b0d674b1ef177cea749c435422223b73a Mon Sep 17 00:00:00 2001 From: Returner_org Date: Sun, 28 Jun 2026 20:16:56 +0300 Subject: [PATCH] =?UTF-8?q?docs(core):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20docstring'=D0=B8=20=D0=BA=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=D0=BC=20envelope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Описаны назначение и параметры success/error/custom_info. Для custom_info добавлено предупреждение использовать её только в крайних случаях вместо success/error. --- src/elexam_core/envelope.py | 125 ++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/elexam_core/envelope.py diff --git a/src/elexam_core/envelope.py b/src/elexam_core/envelope.py new file mode 100644 index 0000000..f0ed8b8 --- /dev/null +++ b/src/elexam_core/envelope.py @@ -0,0 +1,125 @@ +from datetime import datetime, timezone +from ulid import ULID +from typing import Any, Optional + +from elexam_core.context import trace_id_context + + +def success( + data: Optional[Any] = None, + message: str = "OK", + event_type: Optional[str] = None, + metadata: Optional[Any] = None, +) -> dict[str, Any]: + """ + Формирует стандартный envelope успешного ответа или события со статусом ``"success"``. + + Используется во всех эндпоинтах и обработчиках событий, когда операция завершилась + без ошибок. Поле ``errors`` всегда равно ``None``, поле ``data`` содержит результат. + + :param data: Полезная нагрузка ответа/события — объект, список или любое + сериализуемое значение, которое получит клиент. ``None``, если ответ + не предполагает тела (например, DELETE без содержимого). + :param message: Человекочитаемое сообщение о результате операции. + По умолчанию ``"OK"``. + :param event_type: Имя типа события для RabbitMQ-сообщений (например, + ``"exam.published"``). Оборачивается в структуру + ``{"id": , "name": event_type}``. ``None`` для обычных HTTP-ответов. + :param metadata: Дополнительные метаданные, не входящие в основную нагрузку + (например, пагинация, версия снимка). Кладутся в поле ``meta``. + :return: Словарь-envelope с полями ``status``, ``data``, ``message``, + ``trace_id``, ``errors``, ``meta``, ``event_type``, ``processed_at``. + """ + + return { + "status": "success", + "data": data, + "message": message, + "trace_id": trace_id_context.get(), + "errors": None, + "meta": metadata, + "event_type": {"id": str(ULID()), "name": event_type}, + "processed_at": datetime.now(timezone.utc).isoformat(), + } + +def error( + message: str = "ERROR", + errors: Optional[str] = None, + event_type: Optional[str] = None, +) -> dict[str, Any]: + """ + Формирует стандартный envelope ответа об ошибке со статусом ``"error"``. + + Используется во всех обработчиках исключений и в местах, где операция завершилась + неуспешно. Поле ``data`` всегда равно ``None``, поле ``meta`` всегда равно ``None``. + + :param message: Человекочитаемое описание ошибки, предназначенное для отображения + клиенту или логирования. По умолчанию ``"ERROR"``. + :param errors: Детали ошибки — строка с кодом из каталога ошибок, список + валидационных нарушений или иное машиночитаемое описание причины сбоя. + ``None``, если дополнительная детализация не требуется. + :param event_type: Имя типа события для RabbitMQ-сообщений (например, + ``"exam.failed"``). Оборачивается в структуру + ``{"id": , "name": event_type}``. ``None`` для обычных HTTP-ответов. + :return: Словарь-envelope с полями ``status``, ``data``, ``message``, + ``trace_id``, ``errors``, ``meta``, ``event_type``, ``processed_at``. + """ + + return { + "status": "error", + "data": None, + "message": message, + "trace_id": trace_id_context.get(), + "errors": errors, + "meta": None, + "event_type": {"id": str(ULID()), "name": event_type}, + "processed_at": datetime.now(timezone.utc).isoformat(), + } + +def custom_info( + status: str, + data: Optional[Any] = None, + message: Optional[str] = "ERROR", + errors: Optional[Any] = None, + metadata: Optional[Any] = None, + event_type: Optional[str] = None, +) -> dict[str, Any]: + """ + Формирует envelope с произвольным статусом, переданным вызывающим кодом. + + .. warning:: + Использовать эту функцию **не рекомендуется**. Применять её следует только + в крайних случаях, когда стандартные ``success()`` и ``error()`` семантически + не подходят (нестандартный протокол статусов). В подавляющем большинстве + случаев предпочитайте ``success()`` или ``error()``. + + :param status: Произвольная строка-статус, которая будет помещена в поле + ``status`` envelope. Контракт значения полностью на ответственности + вызывающего кода. + :param data: Полезная нагрузка ответа/события — объект, список или любое + сериализуемое значение, которое получит клиент. ``None``, если ответ + не предполагает тела. + :param message: Человекочитаемое сообщение о результате операции. + По умолчанию ``"ERROR"``. + :param errors: Детали ошибки — строка с кодом из каталога ошибок, список + валидационных нарушений или иное машиночитаемое описание причины сбоя. + ``None``, если дополнительная детализация не требуется. + :param metadata: Дополнительные метаданные, не входящие в основную нагрузку. + Кладутся в поле ``meta``. + :param event_type: Имя типа события для RabbitMQ-сообщений. Оборачивается + в структуру ``{"id": , "name": event_type}``. ``None`` для + обычных HTTP-ответов. + :return: Словарь-envelope с полями ``status``, ``data``, ``message``, + ``trace_id``, ``errors``, ``meta``, ``event_type``, ``processed_at``. + """ + + return { + "status": status, + "data": data, + "message": message, + "trace_id": trace_id_context.get(), + "errors": errors, + "meta": metadata, + "event_type": {"id": str(ULID()), "name": event_type}, + "processed_at": datetime.now(timezone.utc).isoformat(), + } \ No newline at end of file