Skip to main content

FastAPI Derive Responses Plugin

fastapi-derive-responses is a Python library that extends FastAPI by automatically generating OpenAPI responses based on your endpoint's source code. This plugin helps you reduce boilerplate code by deriving response statuses and descriptions directly from your code.

With fastapi-derive-responses you can omit ~4 lines on endpoint definition:

@app.get(
    "/add_user",
    responses={
         200: {"description": "User added successfully"},
-        400: {"description": "User already exists"},
-        401: {"description": "Invalid token"},
-        403: {"description": "Only admins and moderators can add users or You are banned"},
-        404: {"description": "Invalid role or User not found"},
    },
)
def add_user(
    current_user_id: Annotated[int, Depends(auth_user)],
    new_user_id: int,
    user_role: str
):
    if statuses[current_user_id] not in ("admin", "moderator"):
        raise HTTPException(403, "Only admins and moderators can add users")
    if new_user_id in statuses:
        raise HTTPException(400, "User already exists")
    if user_role not in ROLES:
        raise HTTPException(400, "Invalid role")
    statuses[new_user_id] = user_role
    return {"message": "User added successfully"}

TODO

  • raise HTTPException(401, detail="Invalid token") in endpoint source -> {401: {description: "Invalid token"}}
  • raise HTTPException(404, detail=f"User with id={id} not found") in endpoint source -> {404: {description: "User with id={id} not found"}}
  • raise HTTPException(404, headers={"X-Error": "User not found"}) in endpoint source -> {404: {headers: {"X-Error": "User not found"}}}
  • Multiple derived responses for the same endpoint merged into one -> {401: {description: "Invalid token OR Token is expired"}}
  • Don't override manually defined responses in decorators
  • ^ Same behavior for dependency functions ^
  • :raises HTTPException: 401 Invalid token in dependency function docstring parses -> {401: {description: "Invalid token"}}
  • Avoid false positives (e.g., raise HTTPException(401) where HTTPException is not from starlette or fastapi)
  • Parse custom classes that inherit from HTTPException
  • Check for custom response models
  • Allow to omit some responses from parsing
  • Code analysis for complex structures in detail and headers

Known Issues

Plugin works through AST parsing, so it may not work correctly with complex code structures or runtime generated code. Also, it may produce false positives: for example, if you raise an exception with name HTTPException yet not from starlette or fastapi and you have imported starlette.HTTPException in the same module but in some isolated scope then your exception will be considered as starlette.HTTPException.

Installation

pip install fastapi-derive-responses

Quick Start

Basic Usage

You can just raise subclasses of starlette.HTTPException in endpoint.

It will propagate {404: {"description": "Item not found"}, 400: {"description": "Invalid item id"}} to OpenAPI schema.

from fastapi import FastAPI, HTTPException
from fastapi_derive_responses import AutoDeriveResponsesAPIRoute

app = FastAPI()
app.router.route_class = AutoDeriveResponsesAPIRoute
# router = APIRouter(route_class=AutoDeriveResponsesAPIRoute) # for router

class CustomExeption(HTTPException):
    ...

@app.get("/items/{item_id}")
def read_item(item_id: int):
    if item_id == 0:
        raise HTTPException(status_code=404, detail="Item not found")
    if item_id == -1:
        raise CustomExeption(status_code=400, detail="Invalid item id")
    return {"id": item_id, "name": "Item Name"}

Example with Dependencies

It will propagate {401: {"description": "Invalid token"}}, {403: {"description": "You are banned"}} and {404: { "description": "User not found"}} to OpenAPI schema.

from typing import Annotated

from fastapi import Depends, FastAPI
from fastapi_derive_responses import AutoDeriveResponsesAPIRoute

app = FastAPI()
app.router.route_class = AutoDeriveResponsesAPIRoute


def auth_user(token: int) -> int:
    """
    Authenticate user

    :raises HTTPException: 401 Invalid token
    :raises HTTPException: 403 You are banned
    :raises HTTPException: 404 User not found
    """
    call_some_func_that_may_raise()
    return token


@app.get("/users/me")
def get_current_user(user_id: Annotated[int, Depends(auth_user)]):
    return {"id": user_id, "role": "admin"}

Also, you can just raise subclasses of starlette.HTTPException in your dependency function:

class CustomException(HTTPException):
    ...

def auth_user(token: int) -> int:
    if token < 100:
        raise HTTPException(401, "Invalid token")
    user_id = token - 100
    if user_id not in statuses:
        raise CustomException(404, "User not found")
    if user_id in banlist:
        raise HTTPException(403, "You are banned")
    return user_id

Also, it works then you import your custom exception from other modules:

# exceptions.py
from starlette.exceptions import HTTPException

class ImportedCustomException(HTTPException):
    ...
# main.py
from exceptions import ImportedCustomException
...

app = FastAPI(title="Custom Exception App")
app.router.route_class = AutoDeriveResponsesAPIRoute

@app.get("/")
def raise_custom_exception():
    raise ImportedCustomException(status_code=601, detail="CustomException!")

Metadata

Release files for fastapi-derive-responses 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-derive-responses 0.1.7
File Size Uploaded Provenance
fastapi_derive_responses-0.1.7.tar.gz 7.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-derive-responses 0.1.7
File Interpreter ABI Platform
fastapi_derive_responses-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 15.4 kB

Release files / fastapi_derive_responses-0.1.7.tar.gz

Download URL fastapi_derive_responses-0.1.7.tar.gz
Size 7.3 kB
Tags Source
SHA-256 checksum
How to use checksums
da30919b5038fb03ba39fa1be4202e24ebf75321d6031e968183fe347c2be841
BLAKE2b-256 checksum
How to use checksums
6781b187509dbc7c02d1555e0c037dadd5ad892ba2beec0676077cf6bcea1fb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.12 Linux/6.17.9-200.nobara.fc43.x86_64

Release files / fastapi_derive_responses-0.1.7-py3-none-any.whl

Download URL fastapi_derive_responses-0.1.7-py3-none-any.whl
Size 8.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85b5589b7f17364079534826c6e8b8ae16c77c789735bc13972ab10afb8be6e2
BLAKE2b-256 checksum
How to use checksums
cec901c3eee4d8f808139be46e677c64241f7eb1666b29497a7e961c99566a91
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.12 Linux/6.17.9-200.nobara.fc43.x86_64

Security for fastapi-derive-responses 0.1.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page