Skip to content

Commit

Permalink
doc: automate ReST API documentation
Browse files Browse the repository at this point in the history
The django extension drf_spectacular allows to generate OpenAPI schema.
Via redoc, this schema can be rendered into a detailed html api
documentation. This api documentation is referenced by Sphinx to be
available on the GitHub pages documentation.

Signed-off-by: Jonas Remmert <jremmert@gmx.net>
  • Loading branch information
jonas-rem committed Jun 5, 2024
1 parent 93ce8ee commit 998ea13
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doc/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ Sphinx==7.3.7
sphinx-book-theme==1.1.2
plantuml==0.3.0
sphinxcontrib-plantuml
sphinxcontrib-httpdomain
sphinxcontrib-redoc
sphinx-autobuild
codespell
tox
7 changes: 7 additions & 0 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Internal ReST APIs
==================

.. The following text is only a placeholder in case the api can not be
generated (e.g. for the pdf version)
The API Documentation is available at https://jonas-rem.github.io/lwm2m_server.
12 changes: 12 additions & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'sphinxcontrib.plantuml',
'sphinx.ext.imgconverter',
'sphinx.ext.todo',
'sphinxcontrib.redoc',
]

templates_path = ['_templates']
Expand All @@ -45,6 +46,17 @@
'custom.css',
]

# Automatically generate ReST API documentation
redoc = [
{
'spec': '../build/generated/openapi-schema.yaml',
'page': 'api',
'embed': True,
},
]
# Specify a more recent version for API Doc v
redoc_uri = 'https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js'

html_theme_options = {
'repository_url': 'https://github.com/jonas-rem/lwm2m_server',
'repository_branch': 'main',
Expand Down
1 change: 1 addition & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ Table of Contents
:maxdepth: 1

documentation
api
weblog
1 change: 1 addition & 0 deletions doc/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ deps =
[testenv:py3-html]
commands =
python ../server/django/manage.py graph_models sensordata -o source/images/erd.svg
python ../server/django/manage.py generate_openapi -o build/generated/openapi-schema.yaml
sphinx-build -E -W --keep-going -b html source build/html

[testenv:py3-pdf]
Expand Down
3 changes: 3 additions & 0 deletions server/django/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ whitenoise==6.6.0
graphviz==0.20.3
pyparsing==3.1.2
pydot==2.0.0

# Generation of API documentation
drf-spectacular==0.27.2
Empty file.
Empty file.
32 changes: 32 additions & 0 deletions server/django/sensordata/management/commands/generate_openapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from django.core.management.base import BaseCommand
from drf_spectacular.generators import SchemaGenerator
import yaml
import os

class Command(BaseCommand):
help = 'Generates the OpenAPI schema'

def add_arguments(self, parser):
parser.add_argument(
'-o',
type=str,
help='File path where the OpenAPI schema should be saved',
default='openapi-schema.yaml'
)

def handle(self, *args, **options):
output_path = options['o']

# Ensure the directory exists
os.makedirs(os.path.dirname(output_path), exist_ok=True)

# Generate the OpenAPI schema
generator = SchemaGenerator()
schema = generator.get_schema(request=None, public=True)
schema_yaml = yaml.dump(schema, default_flow_style=False)

# Write the schema to the specified file
with open(output_path, 'w') as file:
file.write(schema_yaml)

self.stdout.write(self.style.SUCCESS(f'Exported OpenAPI schema to {output_path}'))
1 change: 0 additions & 1 deletion server/django/sensordata/tests/test_restapi_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
TEST_PAYLOAD = [
{
"ep": "qemu_x86",
"res": "3",
"val": {
"instances": [
{
Expand Down
1 change: 1 addition & 0 deletions server/django/sensordata/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


class PostResourceView(APIView):
serializer_class = LwM2MSerializer

def post(self, request):
serializer = LwM2MSerializer(data=request.data, many=False)
Expand Down
14 changes: 14 additions & 0 deletions server/django/server/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"django.contrib.staticfiles",
"django_extensions",
"rest_framework",
"drf_spectacular",
"sensordata",
]

Expand All @@ -90,6 +91,19 @@
'whitenoise.middleware.WhiteNoiseMiddleware', # Add this
]

REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

# Automatic ReST API documentation
SPECTACULAR_SETTINGS = {
'TITLE': 'Leshan ReST API',
'DESCRIPTION': 'The leshan_api is hosted by Django. The API allows the\
Leshan server to add LwM2M resource data to Django. It is \
an internal API and must not be exposed to the internet.',
'VERSION': '1.0.0',
}

ROOT_URLCONF = "server.urls"

TEMPLATES = [
Expand Down

0 comments on commit 998ea13

Please sign in to comment.