Skip to main content

OpenAPI v3 support for Sanic. Document and describe all parameters, including sanic path params. python 3.5+

Project description

Sanic OpenAPI v3e

OpenAPI v3 support for Sanic. Document and describe all parameters, including sanic path params. python 3.5+

Installation

pip install sanic-openapi3e

Usage

Import blueprint and use simple decorators to document routes:

import sanic
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc

app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

@app.get("/user/<user_id:int>")
@doc.summary("Fetches a user by ID")
@doc.response(200, "The user")
async def get_user(request, user_id):
    return sanic.response.json(locals())

app.go_fast()

You'll now have a specification at the URL /openapi/spec.json. Your routes will be automatically categorized by their blueprints' names.

Run these simple examples and point your browser to http://127.0.0.1:8000/swagger to see this in action.

Describe route path parameters

import sanic
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc
app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

@app.get("/examples/test_id/<an_id:int>")
@doc.parameter(name="an_id", description="An ID", required=True, _in="path")
def test_id(request, an_id):
    return sanic.response.json(locals())

app.go_fast()

sanic-openapiv3 will recognise that the path parameter an_id is described with @doc.parameter and will merge the details together.

You may wish to specify that a parameter be limited to a set of choices, such as day-of-week or that it has a minimum value. These can be done for parameters in path, query, header and cookie:

import sanic
import sanic.request
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc

app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

int_min_4 = doc.Schema(
    _type="integer", _format="int32", minimum=4, description="Minimum: 4"
)  

@app.get("/test/some_ids")
@doc.parameter(
    name="ids",
    description="Some IDs",
    required=True,
    choices=[1, 3, 5, 7, 11, 13],
    _in="query",
    schema=doc.Schema.Integers,
)
def test_some_ids(request: sanic.request.Request):
    query = request.query_string
    return sanic.response.json(locals())



@app.get("/examples/test_id_min/<an_id:int>")
@doc.parameter(
    name="an_id", description="An ID", required=True, _in="path", schema=int_min_4
)
def test_id_min(request, an_id: int):
    return sanic.response.json(locals())

app.go_fast()

Describe your tags

OpenAPI uses "tags" (there can be more than one per route) to group the endpoints. It's nice to be able to group your endpoints into tags given by the blueprint's name, but sometimes you will want to give them better names: @doc.tag("tag name"). Better still is to give a description to these tags (which shows up nicely in Swagger UI), so @doc.tag("tag name", description="tag description").

You don't have to add the description more than once, sanic-openapiv3e will make it available, so while you'll want to decorate each endpoint with @doc.tag(...), only one of these will need the description. If you try to set different descriptions for the same tag, sanic-openapiv3e will raise an exception showing the tag name and the conflicting descriptions.

Share and reuse common parameters in your app

You probably have some common parameters that appear in many places in your API. Days of the week? Pagination where the minimum value must be greater than zero? OpenAPI v3 has the concept of "components" which can be shared. Setting them up is easy:

import sanic.request
import sanic.response
from sanic import Sanic
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc


days_of_week = doc.Schema(
    _type="string",
    description="Days of the week, short, English",
    enum=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
)

app = Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

schemas = {
    "int.min4": doc.Schema(
        title="int.min4",
        _type="integer",
        _format="int32",
        minimum=4,
        description="Minimum: 4",
    ),
    "days": days_of_week,
}
components = doc.Components(schemas=schemas)
app.config.OPENAPI_COMPONENTS = components

# ^^ the line above adds these to OAS v3's "components"
# the next two, which would ordinarily live in your blueprints's module,
# reuse these shared components.
int_min_4_ref = doc.Reference("#/components/schemas/int.min4")
dow_ref = doc.Reference("#/components/schemas/days")


@app.get("/simple/01/from/<start>/to/<end>/in/<hops:int>")
@doc.parameter(
    name="start", description="Start day", required=True, _in="path", schema=dow_ref
)
@doc.parameter(
    name="end", description="End day", required=True, _in="path", schema=dow_ref
)
@doc.parameter(
    name="hops",
    description="hops to use",
    required=True,
    _in="path",
    schema=int_min_4_ref,
)
def get_start_end_hops(request, start: str, end: str, hops: int):
    return sanic.response.json(locals())


app.go_fast()

Deprecate route paths or parameters

A parameter can be marked as deprecated=True:

import sanic
import sanic.request
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc

app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

@app.get("/examples/test_parameter__deprecated/<an_id:int>")
@doc.parameter(
    name="an_id", description="An ID", required=True, _in="path", deprecated=True
)
@doc.summary("A path deprecated parameter")
@doc.description("The parameter should be marked as deprecated")
def param__deprecated(request, an_id: int):
    return sanic.response.json(locals())

app.go_fast()

as can a whole route with @doc.deprecated:

import sanic
import sanic.request
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc

app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

@app.get("/examples/test_path__deprecated/<an_id:int>")
@doc.parameter(
    name="an_id",
    description="An ID",
    required=True,
    _in="path",
)
@doc.summary("A path with parameter examples")
@doc.description("This is marked as being deprecated")
@doc.deprecated
def path__deprecated(request, an_id: int):
    return sanic.response.json(locals())

app.go_fast()

Exclude routes from appearing in the OpenAPI spec (and swagger)

Need to soft-launch an endpoint, or keep your swagger simple? Add a @doc.exclude and it won't be in the OpenAPI spec at all (unless you have set your app.config.SHOW_OPENAPI_EXCLUDED = True when a second spec at /openapi/spec.all.json will be created which will have all routes, including excluded.

import sanic
import sanic.request
import sanic.response
from sanic_openapi3e import openapi_blueprint, swagger_blueprint, doc

app = sanic.Sanic(strict_slashes=True)
app.blueprint(openapi_blueprint)
app.blueprint(swagger_blueprint)

@app.get("/test/alpha_release")
@doc.exclude
@doc.parameter(
    name="ids",
    description="Some IDs",
    required=True,
    choices=[1, 3, 5, 7, 11, 13],
    _in="query",
    schema=doc.Schema.Integers,
)
def test_some_ids(request: sanic.request.Request):
    query = request.query_string
    return sanic.response.json(locals())

app.go_fast()

Configure some of the things

app.config.API_VERSION = '1.0.0'
app.config.API_TITLE = 'An API'
app.config.API_DESCRIPTION = 'An API description'

To have a contact, set at least one of (but preferably all) app.config.API_CONTACT_NAME, app.config.API_CONTACT_URL or app.config.API_CONTACT_EMAIL.

To have a license, set app.config.API_LICENSE_NAME and optionally app.config.API_LICENSE_URL (all str, but the Swagger UI .

To have a termsOfService, set app.config.API_TERMS_OF_SERVICE_URL (a str, but the Swagger UI expectes to use this as a URL).

Setting components, security and externalDocs requires you to

  • first create the relevant objects somewhere in your code (near to where you create the app),
  • set the appropriate app.config.OPENAPI_COMPONENTS, app.config.OPENAPI_SECURITY,
    app.config.OPENAPI_EXTERNAL_DOCS.

control spec generation

hide_openapi_self = app.config.get("HIDE_OPENAPI_SELF", True)
show_excluded = app.config.get("SHOW_OPENAPI_EXCLUDED", False)
show_unused_tags = app.config.get("SHOW_OPENAPI_UNUSED_TAGS", False)

In practice, you don't usually want to document the /swagger nor /openapi routes, but by setting app.config.HIDE_OPENAPI_SELF = False you can have them appear in the generated spec (and therefore swagger too).

Your @doc.exclude annotations are always respected, but if your config has app.config.SHOW_OPENAPI_EXCLUDED = True then a second spec at /openapi/spec.all.json is created. You generally won't want these to be on your production deployment, but you may want it for dev and test purposes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sanic-openapi3e-0.5.7.tar.gz (2.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sanic_openapi3e-0.5.7-py3-none-any.whl (2.4 MB view details)

Uploaded Python 3

File details

Details for the file sanic-openapi3e-0.5.7.tar.gz.

File metadata

  • Download URL: sanic-openapi3e-0.5.7.tar.gz
  • Upload date:
  • Size: 2.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.2.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.5.2

File hashes

Hashes for sanic-openapi3e-0.5.7.tar.gz
Algorithm Hash digest
SHA256 d9c52e014a24ddc5bc0aa50e50e4e116a91a2ac9dd89a1273d8a9d8595ac6a17
MD5 d5115b9f7474c0568f08cf0e1ea5a08f
BLAKE2b-256 a9bc89c1513c31cfb6de2a09702d51734a12643d918d6f734e8420a73c658dfd

See more details on using hashes here.

File details

Details for the file sanic_openapi3e-0.5.7-py3-none-any.whl.

File metadata

  • Download URL: sanic_openapi3e-0.5.7-py3-none-any.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.2.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.5.2

File hashes

Hashes for sanic_openapi3e-0.5.7-py3-none-any.whl
Algorithm Hash digest
SHA256 deb57aba18f0d406470b8dbff6cd623cc169b47ddc642e927d7c310cbed041bf
MD5 a9d5dde5b0a0d1a3b080537c685962f7
BLAKE2b-256 fb730b36caabb2d64449ce3299359e689bee28b57996f2e79a5f3fc6e2db4ef9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page