Recent library adopter and first-time issue opener here. :) Thanks to the team for the great library!
The library has a helpful feature of extracting OpenAPI path documentation from the docstring of the handler function. However, I find the feature counter-intuitive from PEP 257 point of view. The best practices defined by the PEP defines that a multi-line docstring consists of a summary line and an elaborate description. I believe that, instead of using the whole docstring as description, the summary line and description should be mapped to OpenAPI summary _and_ description, respectively.
I'm willing to contribute the PR, but would like to clear my idea with the maintainers first.
Here's a self-contained minimal, reproducible, example with my use case:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def hello():
"""Respond with the friendly greeting
This is a long long description of the API call.
"""
return { "greeting": "Hello, world!" }
/openapi.json.{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/": {
"get": {
"summary": "Hello",
"description": "Respond with the friendly greeting\n\nThis is a long long description of the API call.",
"operationId": "hello__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
}
}
}
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/": {
"get": {
"summary": "Respond with the friendly greeting",
"description": "This is a long long description of the API call.",
"operationId": "hello__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
}
}
}
I realize that this is a backward-incompatible change. Nevertheless, I think it's justified for compliance with docstring best practices and a more natural way to write documentation. I suggest the following to mitigate the impact:
summary and description set, ignore the docstringsummary set but description not set, interpret the whole docstring as a description (compatible with the current behavior)summary nor description set, populate both summary and description from the docstring as described aboveAs I said above, I'll be happy to write a PR for this, but I would like to get feedback on the idea first.
What I described can currently be done with decorator arguments, so this feature is just for enhancing productivity and, arguably, the cleanliness of documentation. The alternative is to document the paths like so far.
I would like to add that it would be even better if Python docstrings for parameters were also extracted from the description, in Sphinx notation:
def foobar(id: int):
"""
Get a single Item
Returns the given item from its id.
:param id: The item id, e.g. "2019asa3e8938"
"""
I would like to add that it would be even better if Python docstrings for parameters were also extracted from the description, in Sphinx notation:
def foobar(id: int): """ Get a single Item Returns the given item from its id. :param id: The item id, e.g. "2019asa3e8938" """
Nice idea! I submitted a PR for the original issue but this is a good follow-up.
I think the main idea about the summary and description makes sense, but it will break all my documentation, so I'm skeptical about it. About having the parameters as well, I don't see the real usefulness of having it, considering that we already a nice way to do it and it adds an unnecessary complexity.
Does the documentation have to be mutually exclusive? The usefulness would be to be able to auto-generate user documentation using Sphinx that embeds the API documentation (for example using readthedocs.org, which allows cross-referencing and all that), and it's the de-facto standard way to do Python API documentation.
From what it appears to me, the guiding principle of FastAPI design is that it's possible to do things in multiple ways: One is the DWIM way which should work most of the time. Example: If I just say that a route handler accepts a parameter X, the library figures out from the context if X is a path, query or body parameter, and is correct most of the time. But there is a way to fine-tune everything by explicit configuration. So I can have a plain number from the request body if I want to.
I don't see why this couldn't be applied to documentation. Sphinx autodoc is widely used in the Python community, and allowing developers write API documentation just as they are used to documenting all their functions certainly qualifies as DWIM.
Breaking existing documentation is a valid concern. As a random first-time-contributor-hopeful I can't really decide if it's a blocker, and to which extent the library guarantees backward compatibility.
Thanks for the interest and discussion everyone!
But I see it would be cumbersome to support, being a breaking change, forcing everyone to change to the new behavior, it wouldn't be easy to opt-out, and it would also conflict with the auto-generated summary based on function names.
I also prefer the keyword argument summary that can be found with autocompletion. :shrug:
So I would prefer to keep it as it is. But thanks for the discussion! :coffee:
About the format, OpenAPI supports Markdown, and the docs (Swagger UI) render Markdown. You are free to use reStructuredText if you prefer that, but it won't be rendered by Swagger UI.
If you want to have both, you can add a \f after the main part to add additional info, it won't be added to OpenAPI, and you can extract it for Sphinx if you want, you can check more details here: https://github.com/tiangolo/fastapi/pull/556
Hi @tiangolo,
Thanks for taking the time for detailed response. Fair enough, I'll close this issue as won't do.