Skip to content

Commit cf591cb

Browse files
shrsubrasloria
authored andcommitted
Handling multiple locations in multiple @use_kwargs (#162)
* Handling multiple locations in multiple @use_kwargs * Fix flake8 errors
1 parent b51962a commit cf591cb

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

flask_apispec/apidoc.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,26 @@ def get_parent(self, view):
6969
def get_parameters(self, rule, view, docs, parent=None):
7070
openapi = self.marshmallow_plugin.openapi
7171
annotation = resolve_annotations(view, 'args', parent)
72-
args = merge_recursive(annotation.options)
73-
schema = args.get('args', {})
74-
if is_instance_or_subclass(schema, Schema):
75-
converter = openapi.schema2parameters
76-
elif callable(schema):
77-
schema = schema(request=None)
72+
extra_params = []
73+
for args in annotation.options:
74+
schema = args.get('args', {})
7875
if is_instance_or_subclass(schema, Schema):
7976
converter = openapi.schema2parameters
77+
elif callable(schema):
78+
schema = schema(request=None)
79+
if is_instance_or_subclass(schema, Schema):
80+
converter = openapi.schema2parameters
81+
else:
82+
converter = openapi.fields2parameters
8083
else:
8184
converter = openapi.fields2parameters
82-
else:
83-
converter = openapi.fields2parameters
84-
options = copy.copy(args.get('kwargs', {}))
85-
locations = options.pop('locations', None)
86-
if locations:
87-
options['default_in'] = locations[0]
85+
options = copy.copy(args.get('kwargs', {}))
86+
locations = options.pop('locations', None)
87+
if locations:
88+
options['default_in'] = locations[0]
89+
extra_params += converter(schema, **options) if args else []
8890

8991
rule_params = rule_to_params(rule, docs.get('params')) or []
90-
extra_params = converter(schema, **options) if args else []
9192

9293
return extra_params + rule_params
9394

tests/test_openapi.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,47 @@ def test_responses(self, schemas, path, openapi):
197197

198198
def test_tags(self, path):
199199
assert path['get']['tags'] == ['band']
200+
201+
202+
class TestMultipleLocations:
203+
204+
@pytest.fixture
205+
def function_view(self, app, models, schemas):
206+
class QuerySchema(Schema):
207+
name = fields.Str()
208+
209+
class BodySchema(Schema):
210+
address = fields.Str()
211+
212+
@app.route('/bands/<int:band_id>/')
213+
@use_kwargs(QuerySchema, locations=('query', ))
214+
@use_kwargs(BodySchema, locations=('body', ))
215+
def get_band(**kwargs):
216+
return kwargs
217+
return get_band
218+
219+
@pytest.fixture
220+
def path(self, app, spec, function_view):
221+
converter = ViewConverter(app=app, spec=spec)
222+
paths = converter.convert(function_view)
223+
for path in paths:
224+
spec.path(**path)
225+
return spec._paths['/bands/{band_id}/']
226+
227+
def test_params(self, app, path):
228+
params = path['get']['parameters']
229+
rule = app.url_map._rules_by_endpoint['get_band'][0]
230+
expected = (
231+
[{
232+
'in': 'query',
233+
'name': 'name',
234+
'required': False,
235+
'type': 'string'
236+
}, {
237+
'in': 'body',
238+
'name': 'body',
239+
'required': False,
240+
'schema': {'$ref': '#/definitions/Body'}
241+
}] + rule_to_params(rule)
242+
)
243+
assert params == expected

0 commit comments

Comments
 (0)