課題
FastAPIでAPIサーバーを作っている。
FastAPIは関数の引数や戻り値の型情報を読み取ってOpenAPI(旧Swagger)形式のドキュメントを作ってくれる。
OpenAPIには今のAPIのバージョンを設定するフィールドがあり、ここでAPIのバージョンを管理することができる。
もちろんハードコーディングで管理してもいいのだが、今回はパッケージマネージャーにPoetryを使っているので、 pyproject.toml
内の [tools.poetry]
セクションの version
を動的に読み取るようにすると綺麗に管理できるような気がした。
[tool.poetry]
name = "my_api_server" # <- ついでにこれも表示させたい
version = "12.8.9" # <- これをOpenAPIドキュメントに表示させたい
description = "私のAPIサーバーです。" # <- ついでにこれも表示させたい
authors = ["que9 <example@example.com>"]
...
解決方法
愚直に実装した。なお、TOMLファイルの読み込みには toml パッケージを採用した。
-
poetry add toml
を実行し、toml パッケージをインストールする -
main.py
に以下を仕込む
import os
from typing import Any, Dict
import toml
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
assert os.path.exists("pyproject.toml")
with open("pyproject.toml") as f: # ... ③-1
pyproject_toml = toml.load(f) # ... ③-1
poetry: Dict[str, Any] = pyproject_toml["tool"]["poetry"]
title: str = poetry["name"]
version: str = poetry["version"] # ... ③-2
description: str = poetry["description"]
app.openapi_schema = get_openapi(
title=title,
version=version, # ... ②
description=description,
routes=app.routes,
)
return app.openapi_schema
app.openapi = custom_openapi # ... ①
@app.get("/test")
def test():
return "success"
一応解説すると、 app.openapi
にOpenAPIのスキーマ情報を取得する関数 custom_openapi
を定義している(①)。
OpenAPIのスキーマ情報は fastapi.openapi.utils.get_openapi
に適当に引数を設定すると取得できる(②)。
引数に設定する値はtomlパッケージを使って pyproject.toml
から読み込んでいる(③-1)。
[tool.poetry]
の version
を参照するためには pyproject["tool"]["poetry"]["version"]
のようにしてアクセスできる
今回はバージョンの他にも name
や description
もスキーマ情報として設定したかったので、
pyproject["tool"]["poetry"]
を一時変数に代入してから取得するようにしている(③-2)。
結果
こんな感じ。
/docsの表示
/redocの表示
main.py
を書き換える前はバージョンが0.1.0だったが、書き換えた後は pyproject.toml
記載の値になった。
ついでにAPIの名称や説明文も pyproject.toml
記載の値になった。よしよし。