CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-litestar

Litestar is a powerful, flexible yet opinionated ASGI web framework specifically focused on building high-performance APIs.

Pending
Overview
Eval results
Files

openapi.mddocs/

OpenAPI Documentation

Automatic OpenAPI 3.1 specification generation with customizable documentation, schemas, and interactive API exploration. Litestar provides comprehensive OpenAPI support with multiple documentation interfaces and extensive customization options.

Capabilities

OpenAPI Configuration

Main configuration class for OpenAPI specification generation.

class OpenAPIConfig:
    def __init__(
        self,
        *,
        title: str = "Litestar API",
        version: str = "1.0.0",
        description: str | None = None,
        summary: str | None = None,
        contact: Contact | None = None,
        license: License | None = None,
        servers: list[Server] | None = None,
        terms_of_service: str | None = None,
        external_docs: ExternalDocumentation | None = None,
        security: list[SecurityRequirement] | None = None,
        components: Components | None = None,
        tags: list[Tag] | None = None,
        webhooks: dict[str, PathItem | Reference] | None = None,
        openapi_controller: type[OpenAPIController] | None = None,
        favicon_url: str | None = None,
        root_schema_site: Literal["redoc", "swagger", "rapidoc", "stoplight"] = "redoc",
        enabled_endpoints: set[str] = frozenset({"redoc", "swagger", "openapi.json", "openapi.yaml"}),
        path: str = "/schema",
        create_examples: bool = True,
        plugins: list[OpenAPIPlugin] | None = None,
        operation_id_creator: Callable[[str, str, list[str]], str] | None = None,
        use_handler_docstrings: bool = False,
        by_alias: bool = True,
        prefer_alias: bool = False,
        openapi_version: str = "3.1.0",
    ):
        """
        OpenAPI documentation configuration.

        Parameters:
        - title: API title
        - version: API version
        - description: API description
        - summary: API summary
        - contact: Contact information
        - license: License information
        - servers: Server configurations
        - terms_of_service: Terms of service URL
        - external_docs: External documentation
        - security: Security requirements
        - components: Reusable components
        - tags: API tags for grouping operations
        - webhooks: Webhook definitions
        - openapi_controller: Custom controller for OpenAPI endpoints
        - favicon_url: Favicon URL for documentation UI
        - root_schema_site: Default documentation interface
        - enabled_endpoints: Enabled documentation endpoints
        - path: Base path for documentation endpoints
        - create_examples: Generate examples automatically
        - plugins: OpenAPI generation plugins
        - operation_id_creator: Custom operation ID generator
        - use_handler_docstrings: Include handler docstrings in schema
        - by_alias: Use field aliases in schema
        - prefer_alias: Prefer aliases over original field names
        - openapi_version: OpenAPI specification version
        """

    @property
    def openapi_schema(self) -> OpenAPI:
        """Get the generated OpenAPI schema."""

    def create_openapi_schema_model(self) -> OpenAPI:
        """Create OpenAPI schema model from configuration."""

OpenAPI Controller

Controller that provides OpenAPI documentation endpoints.

class OpenAPIController(Controller):
    path: str = "/schema"
    include_in_schema: bool = False
    
    def __init__(self, owner: Router):
        """
        OpenAPI documentation controller.

        Parameters:
        - owner: Router that owns this controller
        """

    @get(
        path="/openapi.json",
        media_type=MediaType.JSON,
        summary="OpenAPI JSON Schema",
        operation_id="get_openapi_json"
    )
    def get_openapi_json(self) -> dict[str, Any]:
        """Return OpenAPI schema as JSON."""

    @get(
        path="/openapi.yaml", 
        media_type="application/x-yaml",
        summary="OpenAPI YAML Schema",
        operation_id="get_openapi_yaml"
    )
    def get_openapi_yaml(self) -> str:
        """Return OpenAPI schema as YAML."""

    @get(
        path="/redoc",
        media_type=MediaType.HTML,
        summary="Redoc Documentation",
        operation_id="get_redoc"
    )
    def get_redoc(self) -> str:
        """Serve Redoc documentation interface."""

    @get(
        path="/swagger", 
        media_type=MediaType.HTML,
        summary="Swagger UI",
        operation_id="get_swagger_ui"
    )
    def get_swagger_ui(self) -> str:
        """Serve Swagger UI documentation interface."""

    @get(
        path="/rapidoc",
        media_type=MediaType.HTML,
        summary="RapiDoc Documentation", 
        operation_id="get_rapidoc"
    )
    def get_rapidoc(self) -> str:
        """Serve RapiDoc documentation interface."""

    @get(
        path="/stoplight",
        media_type=MediaType.HTML,
        summary="Stoplight Elements",
        operation_id="get_stoplight"
    )
    def get_stoplight(self) -> str:
        """Serve Stoplight Elements documentation interface."""

Response Specification

Classes for defining response schemas and examples.

class ResponseSpec:
    def __init__(
        self,
        *,
        description: str = "Success",
        headers: dict[str, OpenAPIHeader] | None = None,
        content: dict[str, OpenAPIMediaType] | None = None,
        links: dict[str, OpenAPILink] | None = None,
        examples: dict[str, OpenAPIExample] | None = None,
    ):
        """
        OpenAPI response specification.

        Parameters:
        - description: Response description
        - headers: Response headers schema
        - content: Response content schema by media type
        - links: Response links
        - examples: Response examples
        """

    def to_schema(self) -> dict[str, Any]:
        """Convert to OpenAPI response schema."""

class OpenAPIResponse:
    def __init__(
        self,
        description: str,
        *,
        headers: dict[str, OpenAPIHeader] | None = None,
        content: dict[str, OpenAPIMediaType] | None = None,
        links: dict[str, OpenAPILink] | None = None,
    ):
        """OpenAPI response object."""

class OpenAPIMediaType:
    def __init__(
        self,
        *,
        schema: OpenAPISchema | None = None,
        example: Any = None,
        examples: dict[str, OpenAPIExample] | None = None,
        encoding: dict[str, OpenAPIEncoding] | None = None,
    ):
        """OpenAPI media type object."""

class OpenAPIExample:
    def __init__(
        self,
        *,
        summary: str | None = None,
        description: str | None = None,
        value: Any = None,
        external_value: str | None = None,
    ):
        """OpenAPI example object."""

Schema Generation

Utilities for generating OpenAPI schemas from Python types.

def create_schema_for_field_definition(
    field_definition: FieldDefinition,
    generate_examples: bool = True,
    plugins: Sequence[OpenAPISchemaPluginProtocol] | None = None,
) -> OpenAPISchema:
    """
    Create OpenAPI schema for field definition.

    Parameters:
    - field_definition: Field definition to create schema for
    - generate_examples: Whether to generate examples
    - plugins: Schema generation plugins

    Returns:
    OpenAPI schema object
    """

def get_openapi_type_for_complex_type(
    annotation: Any,
    generate_examples: bool = True,
) -> OpenAPISchema:
    """
    Get OpenAPI schema for complex Python types.

    Parameters:
    - annotation: Type annotation
    - generate_examples: Whether to generate examples

    Returns:
    OpenAPI schema object
    """

class OpenAPISchemaCreator:
    def __init__(
        self,
        plugins: Sequence[OpenAPISchemaPluginProtocol] | None = None,
        generate_examples: bool = True,
    ):
        """
        OpenAPI schema creator.

        Parameters:
        - plugins: Schema generation plugins
        - generate_examples: Whether to generate examples
        """

    def create_component_schema(
        self,
        field_definition: FieldDefinition,
    ) -> tuple[OpenAPISchema, str]:
        """
        Create reusable component schema.

        Returns:
        Tuple of (schema, component_key)
        """

    def create_schema(self, field_definition: FieldDefinition) -> OpenAPISchema:
        """Create schema for field definition."""

OpenAPI Data Structures

Core data structures representing OpenAPI specification elements.

class OpenAPI:
    """Root OpenAPI specification object."""
    
    def __init__(
        self,
        *,
        openapi: str = "3.1.0",
        info: Info,
        servers: list[Server] | None = None,
        paths: dict[str, PathItem] | None = None,
        webhooks: dict[str, PathItem | Reference] | None = None,
        components: Components | None = None,
        security: list[SecurityRequirement] | None = None,
        tags: list[Tag] | None = None,
        external_docs: ExternalDocumentation | None = None,
    ):
        """OpenAPI root object."""

class Info:
    """API information object."""
    
    def __init__(
        self,
        *,
        title: str,
        version: str,
        summary: str | None = None,
        description: str | None = None,
        terms_of_service: str | None = None,
        contact: Contact | None = None,
        license: License | None = None,
    ):
        """API info object."""

class Server:
    """Server configuration object."""
    
    def __init__(
        self,
        *,
        url: str,
        description: str | None = None,
        variables: dict[str, ServerVariable] | None = None,
    ):
        """Server object."""

class PathItem:
    """Path item object containing operations."""
    
    def __init__(
        self,
        *,
        summary: str | None = None,
        description: str | None = None,
        servers: list[Server] | None = None,
        parameters: list[Parameter | Reference] | None = None,
        get: Operation | None = None,
        put: Operation | None = None,
        post: Operation | None = None,
        delete: Operation | None = None,
        options: Operation | None = None,
        head: Operation | None = None,
        patch: Operation | None = None,
        trace: Operation | None = None,
    ):
        """Path item object."""

class Operation:
    """Operation object for HTTP methods."""
    
    def __init__(
        self,
        *,
        tags: list[str] | None = None,
        summary: str | None = None,
        description: str | None = None,
        external_docs: ExternalDocumentation | None = None,
        operation_id: str | None = None,
        parameters: list[Parameter | Reference] | None = None,
        request_body: RequestBody | Reference | None = None,
        responses: dict[str, Response | Reference],
        callbacks: dict[str, dict[str, PathItem]] | None = None,
        deprecated: bool = False,
        security: list[SecurityRequirement] | None = None,
        servers: list[Server] | None = None,
    ):
        """Operation object."""

class Components:
    """Reusable components object."""
    
    def __init__(
        self,
        *,
        schemas: dict[str, Schema | Reference] | None = None,
        responses: dict[str, Response | Reference] | None = None,
        parameters: dict[str, Parameter | Reference] | None = None,
        examples: dict[str, Example | Reference] | None = None,
        request_bodies: dict[str, RequestBody | Reference] | None = None,
        headers: dict[str, Header | Reference] | None = None,
        security_schemes: dict[str, SecurityScheme | Reference] | None = None,
        links: dict[str, Link | Reference] | None = None,
        callbacks: dict[str, dict[str, PathItem] | Reference] | None = None,
        path_items: dict[str, PathItem | Reference] | None = None,
    ):
        """Components object."""

Usage Examples

Basic OpenAPI Configuration

from litestar import Litestar, get, post
from litestar.openapi import OpenAPIConfig
from litestar.openapi.spec import Contact, License, Server

# Basic OpenAPI configuration
openapi_config = OpenAPIConfig(
    title="My API",
    version="1.0.0",
    description="A comprehensive API for my application",
    summary="Production-ready API with full documentation",
    contact=Contact(
        name="API Support",
        email="support@example.com", 
        url="https://example.com/support"
    ),
    license=License(
        name="MIT",
        url="https://opensource.org/licenses/MIT"
    ),
    servers=[
        Server(
            url="https://api.example.com",
            description="Production server"
        ),
        Server(
            url="https://staging-api.example.com", 
            description="Staging server"
        ),
        Server(
            url="http://localhost:8000",
            description="Development server"
        )
    ]
)

@get("/users", summary="List Users", description="Retrieve a list of all users")
def get_users() -> list[dict]:
    """Get all users from the system."""
    return [{"id": 1, "name": "Alice"}]

@post("/users", summary="Create User", description="Create a new user")
def create_user(data: dict) -> dict:
    """Create a new user with the provided data."""
    return {"id": 123, **data}

app = Litestar(
    route_handlers=[get_users, create_user],
    openapi_config=openapi_config
)

# Documentation available at:
# /schema/redoc - Redoc interface
# /schema/swagger - Swagger UI
# /schema/openapi.json - JSON schema
# /schema/openapi.yaml - YAML schema

Custom Response Specifications

from litestar.openapi import ResponseSpec
from litestar.status_codes import *

# Define custom response specifications
user_responses = {
    HTTP_200_OK: ResponseSpec(
        description="User retrieved successfully",
        examples={
            "user_example": {
                "summary": "Example user",
                "value": {"id": 1, "name": "Alice", "email": "alice@example.com"}
            }
        }
    ),
    HTTP_404_NOT_FOUND: ResponseSpec(
        description="User not found",
        examples={
            "not_found": {
                "summary": "User not found error",
                "value": {"error": "User not found", "code": 404}
            }
        }
    ),
    HTTP_422_UNPROCESSABLE_ENTITY: ResponseSpec(
        description="Validation error",
        examples={
            "validation_error": {
                "summary": "Validation failed",
                "value": {
                    "error": "Validation failed",
                    "details": [
                        {"field": "email", "message": "Invalid email format"}
                    ]
                }
            }
        }
    )
}

@get(
    "/users/{user_id:int}",
    summary="Get User",
    description="Retrieve a user by ID",
    responses=user_responses,
    tags=["Users"]
)
def get_user(user_id: int) -> dict:
    """Get a user by their ID with detailed error responses."""
    if user_id == 999:
        raise NotFoundException("User not found")
    return {"id": user_id, "name": "Alice", "email": "alice@example.com"}

API Tags and Organization

from litestar.openapi.spec import Tag

# Define API tags
tags = [
    Tag(
        name="Users",
        description="User management operations",
        external_docs={
            "description": "User documentation",
            "url": "https://docs.example.com/users"
        }
    ),
    Tag(
        name="Products", 
        description="Product catalog operations"
    ),
    Tag(
        name="Orders",
        description="Order processing and management"
    )
]

openapi_config = OpenAPIConfig(
    title="E-commerce API",
    version="2.0.0",
    tags=tags
)

@get("/users", tags=["Users"], summary="List all users")
def list_users() -> list[dict]:
    return []

@get("/products", tags=["Products"], summary="List all products")  
def list_products() -> list[dict]:
    return []

@post("/orders", tags=["Orders"], summary="Create new order")
def create_order(data: dict) -> dict:
    return data

Security Schemes

from litestar.openapi.spec import SecurityScheme, SecurityRequirement
from litestar.security.jwt import JWTAuth

# JWT authentication setup
jwt_auth = JWTAuth(
    token_secret="secret-key",
    retrieve_user_handler=lambda token, connection: {"id": 1}
)

# Security schemes for OpenAPI
security_schemes = {
    "BearerAuth": SecurityScheme(
        type="http",
        scheme="bearer",
        bearer_format="JWT",
        description="JWT token authentication"
    ),
    "ApiKeyAuth": SecurityScheme(
        type="apiKey",
        in_="header",
        name="X-API-Key",
        description="API key authentication"
    )
}

# Global security requirements
security = [
    {"BearerAuth": []},  # JWT required by default
    {"ApiKeyAuth": []}   # Or API key
]

openapi_config = OpenAPIConfig(
    title="Secure API",
    version="1.0.0",
    components=Components(security_schemes=security_schemes),
    security=security
)

@get("/protected", summary="Protected endpoint")
def protected_endpoint() -> dict:
    """Endpoint that requires authentication."""
    return {"message": "Access granted"}

@get(
    "/public",
    summary="Public endpoint", 
    security=[],  # Override global security
    exclude_from_auth=True
)
def public_endpoint() -> dict:
    """Public endpoint that doesn't require authentication."""
    return {"message": "Public access"}

app = Litestar(
    route_handlers=[protected_endpoint, public_endpoint],
    openapi_config=openapi_config,
    on_app_init=[jwt_auth.on_app_init]
)

Custom Operation IDs

def create_operation_id(
    route_handler_name: str,
    http_method: str,
    path_components: list[str]
) -> str:
    """Create custom operation IDs."""
    # Convert path components to camelCase
    operation_parts = []
    
    for component in path_components:
        if component.startswith("{") and component.endswith("}"):
            # Parameter - convert to "By" format
            param_name = component[1:-1].split(":")[0]
            operation_parts.append("By" + param_name.title())
        else:
            # Path segment
            operation_parts.append(component.title())
    
    # Combine with HTTP method
    method_name = http_method.lower()
    if method_name == "get" and len(operation_parts) > 1:
        method_name = "get"
    elif method_name == "get":
        method_name = "list"
    elif method_name == "post":
        method_name = "create"
    elif method_name == "put":
        method_name = "update"
    elif method_name == "delete":
        method_name = "delete"
    
    return method_name + "".join(operation_parts)

openapi_config = OpenAPIConfig(
    title="API with Custom Operation IDs",
    version="1.0.0",
    operation_id_creator=create_operation_id
)

# These will generate operation IDs:
# GET /users -> listUsers
# GET /users/{user_id} -> getUserByUserId  
# POST /users -> createUsers
# PUT /users/{user_id} -> updateUserByUserId
# DELETE /users/{user_id} -> deleteUserByUserId

@get("/users")
def get_users() -> list[dict]:
    return []

@get("/users/{user_id:int}")  
def get_user(user_id: int) -> dict:
    return {"id": user_id}

@post("/users")
def create_user(data: dict) -> dict:  
    return data

Documentation with Examples

from litestar.openapi import OpenAPIConfig
from dataclasses import dataclass
from litestar.dto import DataclassDTO

@dataclass
class User:
    name: str
    email: str
    age: int
    id: int | None = None

UserDTO = DataclassDTO[User]

openapi_config = OpenAPIConfig(
    title="API with Examples",
    version="1.0.0",
    create_examples=True,  # Auto-generate examples
    use_handler_docstrings=True  # Include docstrings
)

@post("/users", dto=UserDTO, return_dto=UserDTO)
def create_user(data: User) -> User:
    """
    Create a new user in the system.
    
    This endpoint creates a new user with the provided information.
    The user ID will be automatically generated.
    
    Args:
        data: User information including name, email, and age
        
    Returns:
        Created user with generated ID
        
    Raises:
        ValidationException: If user data is invalid
        ConflictException: If user with email already exists
    """
    data.id = 123
    return data

@get("/users/{user_id:int}", return_dto=UserDTO)
def get_user(user_id: int) -> User:
    """
    Retrieve a specific user by ID.
    
    Args:
        user_id: The unique identifier for the user
        
    Returns:
        User information if found
        
    Raises:
        NotFoundException: If user with given ID doesn't exist
    """
    return User(id=user_id, name="Alice", email="alice@example.com", age=30)

Multiple Documentation Interfaces

# Enable multiple documentation interfaces
openapi_config = OpenAPIConfig(
    title="Multi-Interface API",
    version="1.0.0",
    root_schema_site="redoc",  # Default interface
    enabled_endpoints={
        "redoc",        # http://localhost:8000/schema/redoc
        "swagger",      # http://localhost:8000/schema/swagger  
        "rapidoc",      # http://localhost:8000/schema/rapidoc
        "stoplight",    # http://localhost:8000/schema/stoplight
        "openapi.json", # http://localhost:8000/schema/openapi.json
        "openapi.yaml"  # http://localhost:8000/schema/openapi.yaml
    },
    path="/docs",  # Change base path
    favicon_url="https://example.com/favicon.ico"
)

app = Litestar(
    route_handlers=[...],
    openapi_config=openapi_config
)

# Available documentation:
# /docs (redirects to /docs/redoc)
# /docs/redoc - Redoc interface
# /docs/swagger - Swagger UI
# /docs/rapidoc - RapiDoc interface  
# /docs/stoplight - Stoplight Elements
# /docs/openapi.json - JSON schema
# /docs/openapi.yaml - YAML schema

Custom OpenAPI Controller

from litestar.openapi import OpenAPIController
from litestar import get, Response

class CustomOpenAPIController(OpenAPIController):
    path = "/api-docs"
    
    @get("/custom", media_type="text/html")
    def custom_docs(self) -> Response:
        """Custom documentation page."""
        html_content = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>Custom API Documentation</title>
        </head>
        <body>
            <h1>My API Documentation</h1>
            <p>Welcome to our custom API documentation.</p>
            <ul>
                <li><a href="/api-docs/redoc">Redoc Interface</a></li>
                <li><a href="/api-docs/swagger">Swagger UI</a></li>
                <li><a href="/api-docs/openapi.json">JSON Schema</a></li>
            </ul>
        </body>
        </html>
        """
        return Response(content=html_content, media_type="text/html")

openapi_config = OpenAPIConfig(
    title="Custom Controller API",
    version="1.0.0", 
    openapi_controller=CustomOpenAPIController,
    path="/api-docs"
)

Types

# OpenAPI specification types
OpenAPISchema = dict[str, Any]
SecurityRequirement = dict[str, list[str]]
Reference = dict[str, str]

# Component types
Contact = dict[str, str]
License = dict[str, str]
ExternalDocumentation = dict[str, str]
Tag = dict[str, Any]
ServerVariable = dict[str, Any]

# Schema types
Parameter = dict[str, Any]
RequestBody = dict[str, Any]
Response = dict[str, Any]
Header = dict[str, Any]
Example = dict[str, Any] 
Link = dict[str, Any]
Callback = dict[str, Any]
SecurityScheme = dict[str, Any]
Encoding = dict[str, Any]

# Plugin types
OpenAPIPlugin = Any
OpenAPISchemaPluginProtocol = Protocol

# Operation ID creator type
OperationIDCreator = Callable[[str, str, list[str]], str]

# Field definition type
FieldDefinition = Any

Install with Tessl CLI

npx tessl i tessl/pypi-litestar

docs

application-routing.md

configuration.md

dto.md

exceptions.md

http-handlers.md

index.md

middleware.md

openapi.md

plugins.md

request-response.md

security.md

testing.md

websocket.md

tile.json