Introduction
Litestar Framework
Litestar is a powerful, flexible, highly performant, and opinionated ASGI framework.
The Litestar framework supports Plugins, ships with dependency injection, security primitives, OpenAPI schema generation, MessagePack, middlewares, a great CLI experience, and much more.
Scalar
Scalar is the modern open-source developer experience platform for your APIs.
It support add custom specification extensions (starting with a x-) through its plugin API.
The official custom extensions supported by Scalar are:
- x-scalar-environments
- x-scalar-active-environment
- x-codeSamples
- x-displayName
- x-tagGroups
- x-scalar-ignore
- x-additionalPropertiesName
- x-scalar-stability
- x-badges
- x-enum-descriptions
- x-enum-varnames
- x-scalar-sdk-installation
Minimal Example
# app.py
import enum
import pydantic
from litestar import Litestar, get
from litestar.openapi import OpenAPIConfig
from litestar.openapi.plugins import ScalarRenderPlugin
class Weather(enum.IntEnum):
SUNNY = 1
RAINY = 2
CLOUDY = 3
class WeatherPredict(pydantic.BaseModel):
city: str
weather: Weather = pydantic.Field(description="The weather condition")
@get("/city/{name:str}")
async def get_weather(name: str) -> WeatherPredict:
return WeatherPredict(city=name, weather=Weather.SUNNY)
plugins = []
app = Litestar(
route_handlers=[get_weather],
openapi_config=OpenAPIConfig(
title="Litestar Example",
description="Example of Litestar with Scalar OpenAPI docs",
version="0.0.1",
render_plugins=[ScalarRenderPlugin()],
),
plugins=plugins,
)
Open Scalar OpenAPI Document
$ litestar runIt will display a great CLI interface like below.
Visit http://127.0.0.1:8000/schema/scalar, you will see the enum field rendered like below.
Support using The x-enum-descriptions Extension
Below is the screenshot of the OpenAPI document rendered by ScalarRenderPlugin with enum field showing additional description using the x-enum-descriptions extension.
The highlighted lines is all you need to add to your code. The EnumSchemaPlugin modifies the enum field schema to add x-enumDescriptions property. It is then used by the x-enum-descriptions extension.
# app.py
import dataclassesimport enum
from typing import Optional
import pydantic
from litestar import Litestar, get
from litestar.openapi import OpenAPIConfig
from litestar.openapi.plugins import ScalarRenderPlugin
from litestar.openapi.spec import Reference, Schemafrom litestar.plugins import OpenAPISchemaPlugin
class Weather(enum.IntEnum):
SUNNY = 1
RAINY = 2
CLOUDY = 3
@classmethod def get_openapi_descriptions(cls): mapper = { cls.SUNNY: "Sunny weather", cls.RAINY: "Rainy weather", cls.CLOUDY: "Cloudy weather", } return [mapper[i] for i in cls]
class WeatherPredict(pydantic.BaseModel):
city: str
weather: Weather = pydantic.Field(description="The weather condition")
@dataclasses.dataclassclass CustomSchema(Schema): x_enum_descriptions: Optional[list[str]] = None @property def _exclude_fields(self) -> set[str]: return {"x_enum_descriptions"} @classmethod def copy_from(cls, schema: Schema): return CustomSchema(**schema.__dict__) def to_schema(self) -> dict: schema = super().to_schema() schema |= {"x-enumDescriptions": self.x_enum_descriptions} return schema
class EnumSchemaPlugin(OpenAPISchemaPlugin): @staticmethod def is_plugin_supported_type(value): return False def is_plugin_supported_field(self, field_definition) -> bool: return type(field_definition.annotation) is enum.EnumType def to_openapi_schema(self, field_definition, schema_creator): schema = schema_creator.for_enum_field(field_definition) if isinstance(schema, Reference): if getattr(field_definition.annotation, "get_openapi_descriptions", None): registered_schema = schema_creator.schema_registry.from_reference(schema) new_schema = CustomSchema.copy_from(registered_schema.schema) new_schema.x_enum_descriptions = field_definition.annotation.get_openapi_descriptions() registered_schema.schema = new_schema return schema raise RuntimeError("Never execute this line, it is unreachable code.")
@get("/city/{name:str}")
async def get_weather(name: str) -> WeatherPredict:
return WeatherPredict(city=name, weather=Weather.SUNNY)
plugins = [EnumSchemaPlugin()]
app = Litestar(
route_handlers=[get_weather],
openapi_config=OpenAPIConfig(
title="Litestar Example",
description="Example of Litestar with Scalar OpenAPI docs",
version="0.0.1",
render_plugins=[ScalarRenderPlugin()],
),
plugins=plugins,
)