- New packages/kaya-openapi with OpenAPIMixin, @operation decorator, and generate_spec() that walks the routing tree - Enables kaya-core's Tree.register to expose the original handler callback as an instance attribute for metadata introspection - Registers GET /openapi.json and GET /docs (Swagger UI) routes - Supports and path parameters, docstring descriptions, @operation metadata, and excludes wildcard/WS routes - Adds example/openapi.py, updates CI, README, and requirements
3.3 KiB
kaya-openapi
Automatic OpenAPI specification generation for the Kaya lightweight ASGI web framework.
The package provides an OpenAPIMixin that inspects a KayaApp's routing
tree and serves:
- an OpenAPI 3.1 JSON document (default:
GET /openapi.json) - a Swagger UI page to browse it interactively (default:
GET /docs)
Usage
from kaya.core import HttpContext, KayaApp
from kaya.openapi import OpenAPIMixin, operation
app = KayaApp(mixins=[OpenAPIMixin(title='My API', version='1.0.0')])
@app.GET('/users/${user_id:int}')
@operation(summary='Get a user',
tags=['users'],
responses={
200: {'description': 'The user'},
404: {'description': 'User not found'},
})
async def get_user(ctx: HttpContext, user_id: int) -> None:
...
Run the app with any ASGI/RSGI server and open http://localhost:8000/docs.
How routes are mapped
- Static segments and parameters are converted to OpenAPI path templating:
/users/${user_id}→/users/{user_id}(string path parameter)/users/${user_id:int}→/users/{user_id}(integer path parameter)
- Wildcard routes (
*) are skipped: they cannot be expressed in OpenAPI path syntax. - Websocket routes are skipped: OpenAPI does not model websockets.
- Method-agnostic routes (registered with
app.route(path)without methods) are documented under all standard HTTP methods, since they respond to all of them. - The mixin's own endpoints are excluded from the document unless
include_self=True.
The document is generated on every request to the spec endpoint, so routes registered after the mixin is applied are always included.
Operation metadata
The @operation decorator attaches OpenAPI metadata to a route handler.
All fragments are plain dicts merged verbatim into the generated operation
object, so any valid OpenAPI 3.1 construct can be used:
@operation(summary='...', # operation summary
description='...', # defaults to the handler docstring
tags=['users'],
operation_id='getUser',
request_body={...}, # OpenAPI requestBody object
responses={200: {...}}, # per-status-code response objects
parameters=[...], # extra/overriding parameter objects
deprecated=False,
hidden=False) # exclude from the document
parameters entries whose name and in match an auto-generated path
parameter override it; all others are appended.
Configuration
OpenAPIMixin(
title='My API', # info.title (required)
version='1.0.0', # info.version (required)
description='', # info.description
spec_path='/openapi.json', # where the JSON document is served
docs_path='/docs', # where Swagger UI is served
servers=[{'url': 'https://api.example.com'}],
openapi_version='3.1.0',
include_self=False, # include spec/docs endpoints in the document
)
The document can also be generated programmatically without serving it:
from kaya.openapi import generate_spec
spec = generate_spec(app, title='My API', version='1.0.0')