Skip to content

Commit

Permalink
Merge pull request #40 from channelcat/location
Browse files Browse the repository at this point in the history
Location
  • Loading branch information
Typhon committed Sep 5, 2017
2 parents 561371c + 60053fe commit f0253ae
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 33 deletions.
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -42,6 +42,12 @@ from sanic_openapi import doc
@doc.produces({ "user": { "name": str, "id": int } })
async def get_user(request, user_id):
...

@app.post("/user")
@doc.summary("Creates a user")
@doc.consumes({"user": { "name": str }}, location="body")
async def create_user(request):
...
```

### Model your input/output
Expand Down
3 changes: 2 additions & 1 deletion examples/cars/blueprints/car.py
Expand Up @@ -26,7 +26,8 @@ def car_get(request, car_id):

@blueprint.put("/<car_id:int>", strict_slashes=True)
@doc.summary("Updates a car")
@doc.consumes(Car)
@doc.consumes(Car, location='body')
@doc.consumes({'AUTHORIZATION': str}, location='header')
@doc.produces(Car)
def car_put(request, car_id):
return json(test_car)
Expand Down
2 changes: 1 addition & 1 deletion sanic_openapi/__init__.py
@@ -1,5 +1,5 @@
from .openapi import blueprint as openapi_blueprint
from .swagger import blueprint as swagger_blueprint

__version__ = '0.3.0'
__version__ = '0.4.0'
__all__ = ['openapi_blueprint', 'swagger_blueprint']
25 changes: 20 additions & 5 deletions sanic_openapi/doc.py
Expand Up @@ -189,7 +189,7 @@ def serialize_schema(schema):
# --------------------------------------------------------------- #


class RouteSpec:
class RouteSpec(object):
consumes = None
consumes_content_type = None
produces = None
Expand All @@ -203,9 +203,21 @@ class RouteSpec:

def __init__(self):
self.tags = []
self.consumes = []
super().__init__()


class RouteField(object):
field = None
location = None
required = None

def __init__(self, field, location=None, required=False):
self.field = field
self.location = location
self.required = required


route_specs = defaultdict(RouteSpec)


Expand Down Expand Up @@ -255,19 +267,22 @@ def inner(func):
return inner


def consumes(*args, content_type=None):
def consumes(*args, content_type=None, location='query', required=False):
def inner(func):
if args:
route_specs[func].consumes = args[0] if len(args) == 1 else args
route_specs[func].consumes_content_type = content_type
for arg in args:
field = RouteField(arg, location, required)
route_specs[func].consumes.append(field)
route_specs[func].consumes_content_type = content_type
return func
return inner


def produces(*args, content_type=None):
def inner(func):
if args:
route_specs[func].produces = args[0] if len(args) == 1 else args
field = RouteField(args[0])
route_specs[func].produces = field
route_specs[func].produces_content_type = content_type
return func
return inner
Expand Down
57 changes: 32 additions & 25 deletions sanic_openapi/openapi.py
Expand Up @@ -84,31 +84,38 @@ def build_spec(app, loop):
getattr(app.config, 'API_PRODUCES_CONTENT_TYPES', ['application/json'])

# Parameters - Path & Query String
path_parameters = [{
**serialize_schema(parameter.cast),
'required': True,
'in': 'path',
'name': parameter.name,
} for parameter in route.parameters]
query_string_parameters = []
body_parameters = []

if route_spec.consumes:
if _method in ('GET', 'DELETE', 'POST'):
spec = serialize_schema(route_spec.consumes)
if 'properties' in spec:
for name, prop_spec in spec['properties'].items():
query_string_parameters.append({
**prop_spec,
'in': 'query',
'name': name,
})
route_parameters = []
for parameter in route.parameters:
route_parameters.append({
**serialize_schema(parameter.cast),
'required': True,
'in': 'path',
'name': parameter.name
})

for consumer in route_spec.consumes:
spec = serialize_schema(consumer.field)
if 'properties' in spec:
for name, prop_spec in spec['properties'].items():
route_param = {
**prop_spec,
'required': consumer.required,
'in': consumer.location,
'name': name
}
else:
body_parameters.append({
**serialize_schema(route_spec.consumes),
'in': 'body',
'name': 'body',
})
route_param = {
**spec,
'required': consumer.required,
'in': consumer.location,
'name': consumer.field.name if hasattr(consumer.field, 'name') else 'body'
}

if '$ref' in route_param:
route_param["schema"] = {'$ref': route_param['$ref']}
del route_param['$ref']

route_parameters.append(route_param)

endpoint = remove_nulls({
'operationId': route_spec.operation or route.name,
Expand All @@ -117,7 +124,7 @@ def build_spec(app, loop):
'consumes': consumes_content_types,
'produces': produces_content_types,
'tags': route_spec.tags or None,
'parameters': path_parameters + query_string_parameters + body_parameters,
'parameters': route_parameters,
'responses': {
"200": {
"description": None,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_types.py
Expand Up @@ -14,7 +14,7 @@ def test_list_default():
app.blueprint(openapi_blueprint)

@app.put('/test')
@doc.consumes(doc.List(int, description="All the numbers"))
@doc.consumes(doc.List(int, description="All the numbers"), location="body")
def test(request):
return json({"test": True})

Expand Down

0 comments on commit f0253ae

Please sign in to comment.