Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions litellm/proxy/common_utils/swagger_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
from typing import Any, Dict

from pydantic import BaseModel, Field
Expand Down Expand Up @@ -31,11 +32,25 @@ def get_status_code(exception):
return 500 # Internal Server Error as default


# Create error responses
def _exception_description(exception):
"""Return a normalized description for OpenAPI / JSDoc consumers.

Uses the class's own docstring (not an inherited one) so the rendered Swagger
description matches the historical short-form (the class name) when only an
upstream library defined a docstring. ``cleandoc`` strips the source-code
indentation that would otherwise leak into the generated JSDoc comment in
``ui/litellm-dashboard/src/lib/http/schema.d.ts``.
"""
doc = exception.__doc__
if not doc:
return exception.__name__
return inspect.cleandoc(doc)


ERROR_RESPONSES = {
get_status_code(exception): {
"model": ErrorResponse,
"description": exception.__doc__ or exception.__name__,
"description": _exception_description(exception),
}
for exception in LITELLM_EXCEPTION_TYPES
}
Expand Down
33 changes: 33 additions & 0 deletions tests/test_litellm/proxy/common_utils/test_swagger_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import inspect

from litellm.exceptions import RateLimitError
from litellm.proxy.common_utils.swagger_utils import (
ERROR_RESPONSES,
_exception_description,
)


class _ChildWithoutDoc(RateLimitError):
pass


def test_exception_description_dedents_multiline_docstring():
description = _exception_description(RateLimitError)

assert RateLimitError.__doc__ is not None
assert RateLimitError.__doc__.startswith("\n ")
assert description == inspect.cleandoc(RateLimitError.__doc__)
assert "\n " not in description


def test_exception_description_falls_back_to_name_when_no_own_doc():
assert _ChildWithoutDoc.__doc__ is None
assert _exception_description(_ChildWithoutDoc) == "_ChildWithoutDoc"


def test_rate_limit_error_response_description_is_dedented():
rate_limit_response = ERROR_RESPONSES[429]

description = rate_limit_response["description"]
assert description.startswith("Unified rate-limit error.")
assert "\n " not in description
Loading