Ekaropolus 0eb2b393f2
All checks were successful
continuous-integration/drone/push Build is passing
SAMI Functionality add
2025-09-16 16:18:45 -06:00

58 lines
1.8 KiB
Python

from __future__ import annotations
import uuid, traceback
from django.conf import settings
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import ValidationError as DRFValidationError
from pydantic import ValidationError as PydValidationError
def envelope_exception_handler(exc, context):
"""
Envuelve *todas* las excepciones DRF en:
{ ok: false, code, message, errors?, hint?, trace_id, detail?(DEBUG) }
"""
resp = drf_exception_handler(exc, context)
trace_id = str(uuid.uuid4())
if resp is not None:
# DRF ya resolvió un status_code razonable
code = getattr(exc, "default_code", "error")
message = None
if isinstance(exc, DRFValidationError):
message = "Validation error"
else:
# fallback a string corto
message = str(getattr(exc, "detail", "")) or exc.__class__.__name__
data = {
"ok": False,
"code": code,
"message": message,
"errors": resp.data, # DRF normaliza los errores aquí
"hint": None,
"trace_id": trace_id,
}
if settings.DEBUG:
data["detail"] = _short_trace()
return Response(data, status=resp.status_code)
# Excepción no manejada por DRF -> 500
data = {
"ok": False,
"code": "server_error",
"message": "Unexpected server error",
"hint": None,
"trace_id": trace_id,
}
if settings.DEBUG:
data["detail"] = _short_trace()
return Response(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def _short_trace():
try:
return "\n".join(traceback.format_exc().splitlines()[-6:])
except Exception:
return None