generate OpenAPI document and validate request&response with Python annotations.
Project description
Spectree
Yet another library to generate OpenAPI document and validate request & response with Python annotations.
Features
- Less boilerplate code, only annotations, no need for YAML :sparkles:
- Generate API document with Redoc UI or Swagger UI :yum:
- Validate query, JSON data, response data with pydantic :wink:
- Current support:
- Flask
- Falcon
- Starlette
Quick Start
install with pip: pip install spectree
Examples
Check the examples folder.
Step by Step
- Define your data structure used in (query, json, headers, cookies, resp) with
pydantic.BaseModel
- create
spectree.SpecTree
instance with the web framework name you are using, likeapi = SpecTree('flask')
api.validate
decorate the route withquery
json
headers
cookies
resp
tags
- access these data with
context(query, json, headers, cookies)
(of course, you can access these from the original place where the framework offered)- flask:
request.context
- falcon:
req.context
- starlette:
request.context
- flask:
- register to the web application
api.register(app)
- check the document at URL location
/apidoc/redoc
or/apidoc/swagger
If the request doesn't pass the validation, it will return a 422 with JSON error message(ctx, loc, msg, type).
Demo
Try it with http post :8000/api/user name=alice age=18
. (if you are using httpie
)
Flask
from flask import Flask, request, jsonify
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response
class Profile(BaseModel):
name: constr(min_length=2, max_length=40) # Constrained Str
age: int = Field(
...,
gt=0,
lt=150,
description='user age(Human)'
)
class Message(BaseModel):
text: str
app = Flask(__name__)
api = SpecTree('flask')
@app.route('/api/user', methods=['POST'])
@api.validate(json=Profile, resp=Response('HTTP_404', HTTP_200=Message), tags=['api'])
def user_profile():
"""
verify user profile (summary of this endpoint)
user's name, user's age, ... (long description)
"""
print(request.context.json) # or `request.json`
return jsonify(text='it works')
if __name__ == "__main__":
api.register(app) # if you don't register in api init step
app.run(port=8000)
Falcon
import falcon
from wsgiref import simple_server
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response
class Profile(BaseModel):
name: constr(min_length=2, max_length=40) # Constrained Str
age: int = Field(
...,
gt=0,
lt=150,
description='user age(Human)'
)
class Message(BaseModel):
text: str
api = SpecTree('falcon')
class UserProfile:
@api.validate(json=Profile, resp=Response('HTTP_404', HTTP_200=Message), tags=['api'])
def on_post(self, req, resp):
"""
verify user profile (summary of this endpoint)
user's name, user's age, ... (long description)
"""
print(req.context.json) # or `req.media`
resp.media = {'text': 'it works'}
if __name__ == "__main__":
app = falcon.API()
app.add_route('/api/user', UserProfile())
api.register(app)
httpd = simple_server.make_server('localhost', 8000, app)
httpd.serve_forever()
Starlette
import uvicorn
from starlette.applications import Starlette
from starlette.routing import Route
from starlette.responses import JSONResponse
from pydantic import BaseModel, Field, constr
from spectree import SpecTree, Response
class Profile(BaseModel):
name: constr(min_length=2, max_length=40) # Constrained Str
age: int = Field(
...,
gt=0,
lt=150,
description='user age(Human)'
)
class Message(BaseModel):
text: str
api = SpecTree('starlette')
@api.validate(json=Profile, resp=Response('HTTP_404', HTTP_200=Message), tags=['api'])
async def user_profile(request):
"""
verify user profile (summary of this endpoint)
user's name, user's age, ... (long description)
"""
print(request.context.json) # or await request.json()
return JSONResponse({'text': 'it works'})
if __name__ == "__main__":
app = Starlette(routes=[
Route('/api/user', user_profile, methods=['POST']),
])
api.register(app)
uvicorn.run(app)
FAQ
ValidationError: missing field for headers
The HTTP headers' keys in Flask are capitalized, in Falcon are upper cases, in Starlette are lower cases.
You can use pydantic.root_validators(pre=True)
to change all the keys into lower cases or upper cases.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.