Added docs generation
This commit is contained in:
41
.github/workflows/apidocs.yml
vendored
Normal file
41
.github/workflows/apidocs.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
name: Generate and deploy API documentation
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["master"]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||||
|
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Single deploy job since we're just deploying
|
||||||
|
deploy:
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.9'
|
||||||
|
- run: pip install -e .
|
||||||
|
- run: spoolman_docs
|
||||||
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v3
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v1
|
||||||
|
with:
|
||||||
|
path: 'docs/'
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v2
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -71,6 +71,7 @@ instance/
|
|||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
docs/
|
||||||
|
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
.pybuilder/
|
.pybuilder/
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ version = "0.1.0"
|
|||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = {text = "AGPL-3.0-only"}
|
license = {text = "AGPL-3.0-only"}
|
||||||
|
dynamic = ["dependencies"]
|
||||||
|
|
||||||
|
[tool.setuptools.dynamic]
|
||||||
|
dependencies = {file = ["requirements.txt"]}
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
select = ["ALL"]
|
select = ["ALL"]
|
||||||
@@ -16,3 +20,9 @@ target-version = "py39"
|
|||||||
line-length = 120
|
line-length = 120
|
||||||
target-version = ['py39']
|
target-version = ['py39']
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=67.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
spoolman_docs = "spoolman.docs:generate_docs"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from . import filament, models, spool, vendor
|
|||||||
# ruff: noqa: D103
|
# ruff: noqa: D103
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="Spoolson REST API v1",
|
title="Spoolman REST API v1",
|
||||||
version="1.0.0",
|
version="1.0.0",
|
||||||
root_path_in_servers=False,
|
root_path_in_servers=False,
|
||||||
responses={404: {"model": models.Message}},
|
responses={404: {"model": models.Message}},
|
||||||
|
|||||||
67
spoolman/docs.py
Normal file
67
spoolman/docs.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
"""Functions for generating documentation."""
|
||||||
|
|
||||||
|
from contextlib import suppress
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.openapi.utils import get_openapi
|
||||||
|
|
||||||
|
from spoolman.api.v1.router import app as v1_app
|
||||||
|
|
||||||
|
|
||||||
|
def generate_openapi(app: FastAPI) -> dict[str, Any]:
|
||||||
|
"""Generate the OpenAPI document for a specific FastAPI app.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app (FastAPI): The FastAPI app.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict[str, Any]: The OpenAPI document.
|
||||||
|
"""
|
||||||
|
return get_openapi(
|
||||||
|
title=app.title,
|
||||||
|
version=app.version,
|
||||||
|
openapi_version=app.openapi_version,
|
||||||
|
description=app.description,
|
||||||
|
routes=app.routes,
|
||||||
|
contact=app.contact,
|
||||||
|
license_info=app.license_info,
|
||||||
|
servers=app.servers,
|
||||||
|
tags=app.openapi_tags,
|
||||||
|
terms_of_service=app.terms_of_service,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_docs() -> None:
|
||||||
|
"""Generate documentation for this service in the docs/ directory."""
|
||||||
|
|
||||||
|
with suppress(FileExistsError):
|
||||||
|
Path("docs").mkdir()
|
||||||
|
|
||||||
|
spec = json.dumps(generate_openapi(v1_app))
|
||||||
|
|
||||||
|
with Path("docs", "index.html").open("w") as f:
|
||||||
|
f.write(
|
||||||
|
f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Spoolson REST API v1 - ReDoc</title>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||||
|
<link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
|
||||||
|
<style> body {{margin: 0; padding: 0; }} </style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="redoc-container"></div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"> </script>
|
||||||
|
<script>
|
||||||
|
var spec = {spec};
|
||||||
|
Redoc.init(spec, {{}}, document.getElementById("redoc-container"));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>""",
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user