Skip to content

Commit

Permalink
Merge 6509cfb into b652e27
Browse files Browse the repository at this point in the history
  • Loading branch information
strongbugman authored Aug 17, 2018
2 parents b652e27 + 6509cfb commit 922c95f
Show file tree
Hide file tree
Showing 9 changed files with 547 additions and 120 deletions.
15 changes: 15 additions & 0 deletions examples/docs/item/get.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Get single item
---
tags:
- item
parameters:
- name: id
type: integer
in: path
required: True
minimum: 1
responses:
200:
description: OK
schema:
$ref: '#/definitions/Item'
26 changes: 26 additions & 0 deletions examples/docs/item/put.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Update single item
---
tags:
- item
parameters:
- name: id
type: integer
in: path
required: True
minimum: 1
- name: Item
in: body
schema:
type: object
required:
- name
properties:
name:
type: string
maxLength: 31
description: global unique
responses:
200:
description: OK
schema:
$ref: '#/definitions/Item'
25 changes: 25 additions & 0 deletions examples/docs/items/get.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Get all items
---
tags:
- item
parameters:
- name: type
type: string
in: query
required: True
maxLength: 10
responses:
200:
description: OK
schema:
$ref: '#/definitions/Items'
401:
description: Auth required
definitions:
Items:
type: object
properties:
objects:
type: array
items:
$ref: "#/definitions/Item"
25 changes: 25 additions & 0 deletions examples/docs/items/post.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Create item
---
tags:
- item
parameters:
- name: Item
in: body
schema:
type: object
required:
- name
- type
properties:
name:
type: string
maxLength: 31
description: global unique
type:
type: string
maxLength: 10
responses:
201:
description: OK
schema:
$ref: '#/definitions/Item'
16 changes: 16 additions & 0 deletions examples/docs/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
swagger: '2.0'
info:
title: 'ParsedMethodView Example'
description: 'ParsedMethodView Example'
version: '0.1'

definitions:
Item:
type: object
properties:
id:
type: integer
name:
type: string
type:
type: string
13 changes: 13 additions & 0 deletions examples/docs/user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Get single user by id
---
tags:
- Function
parameters:
- name: id
type: integer
in: query
required: True
minimum: 1
responses:
200:
description: OK
177 changes: 177 additions & 0 deletions examples/parsed_view_func.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
"""
Example of auto load doc file by endpoint name(view function/method name),
parsed by flask_restful.reqparse.RequestParser and validated by jsonschema
"""
import os

from flask import Flask, request, jsonify, Response
from flask.views import MethodView
from flasgger import Swagger


app = Flask(__name__)
app.config['SWAGGER'] = {
'title': 'Flasgger ParsedMethodView Example',
'doc_dir': './examples/docs/'
}
swag = Swagger(
app,
template_file=os.path.join(
os.getcwd(), 'examples', 'docs', 'template.yml'),
parse=True)


class ItemsView(MethodView):
"""
Flasgger will try to load "./examples/docs/items/{method}.yml" as
swagger document
"""
def get(self):
"""
If we set "parse" is True in Flasgger app, we will get parsed and
validated data stored in "flask.request.parsed_data".
In "parsed_data", different location's var stored in different key,
there is a map between RequestParser's location and swagger
doc's "in" parameter, eg: 'query' -> 'args'.See
"Swagger.SCHEMA_LOCATIONS" for more locations
"""
return jsonify(
[{'name': 'test', 'id': 1, 'type': request.parsed_data['args']['type']},
{'name': 'test2', 'id': 2, 'type': request.parsed_data['args']['type']}])

def post(self):
return jsonify(
{'name': request.parsed_data['json']['name'], 'id': 3,
'type': request.parsed_data['json']['type']})


class ItemMethodView(MethodView):
def get(self, id):
return jsonify({'name': 'test', 'id': id, 'type': 'NORMAL'})

def put(self, id):
return jsonify(
{'name': request.parsed_data['json']['name'], 'id': 3, 'type': 'NORMAL'})


class EmptyView(MethodView):
"""In this view, we do not provide api doc"""
def get(self):
return Response(status=200)


@app.route('/api/auth/<group>/', methods=['POST'])
def auth(group):
"""Auth
---
tags:
- Function
parameters:
- name: group
in: path
type: string
required: true
- name: Item
in: body
schema:
type: object
required:
- name
- code
- data
properties:
name:
type: string
code:
type: string
data:
type: object
required:
- password
properties:
password:
type: string
date:
type: string
definitions:
User:
type: object
properties:
id:
type: integer
name:
type: string
group:
type: integer
responses:
200:
description: ok
schema:
$ref: '#/definitions/User'
examples:
{'id': 1, 'name': 'test', 'group': 1}
403:
description: Auth failed
400:
description: Miss name or code
"""
if request.parsed_data['json']['data']['password'] != 'test':
return Response(status=403)
return jsonify({'id': 1, 'name': request.parsed_data['json']['name'],
'group': request.parsed_data['path']['group']})


@app.route('/api/user/')
def user():
"""Flasgger will try to load './examples/docs/user.yml' as swagger doc
"""
return jsonify({'id': request.parsed_data['args']['id'], 'name': 'test'})


app.add_url_rule(
'/api/items/', view_func=ItemsView.as_view(name='items'),
methods=['GET', 'POST'])
app.add_url_rule(
'/api/items/<int:id>/', view_func=ItemMethodView.as_view(name='item'),
methods=['GET', 'PUT'])
app.add_url_rule(
'/api/empty/', view_func=EmptyView.as_view(name='empty'),
methods=['GET'])


def test_swag(client, specs_data):
"""
This test is runs automatically in Travis CI
:param client: Flask app test client
:param specs_data: {'url': {swag_specs}} for every spec in app
"""
res = client.get('/api/items/')
assert res.status_code == 400
res = client.get('/api/items/?type=myLengthIsTooLong')
assert res.status_code == 400
res = client.get('/api/items/?type=NORMAL')

assert res.status_code == 200
res = client.get('/api/items/1/')
assert res.status_code == 200
res = client.put('/api/items/1/')
assert res.status_code == 400
res = client.put('/api/items/1/', json={'name': 'test'})
assert res.status_code == 200

res = client.post('/api/auth/1/', json={'name': 'miss code'})
assert res.status_code == 400
res = client.post(
'/api/auth/1/',
json={'name': 'test', 'code': 'test', 'data': {'password': 'test'}})
assert res.status_code == 200
res = client.post(
'/api/auth/1/',
json={'name': 'test', 'code': 'test', 'data': {'password': 'wrong'}})
assert res.status_code == 403


if __name__ == '__main__':
app.run(debug=True)
Loading

0 comments on commit 922c95f

Please sign in to comment.