noirbizarre / flask-restplus

Fully featured framework for fast, easy and documented API development with Flask
http://flask-restplus.readthedocs.org
Other
2.73k stars 507 forks source link

Multiple argument locations breaks doc #380

Open lamehost opened 6 years ago

lamehost commented 6 years ago

Hello,

Multiple argument locations like the following

post_parser = reqparse.RequestParser()
post_parser.add_argument(
    'sessions',
    type=list,
    help='List of sessions to be created',
    location=['body', 'json']
)

Breaks documentation:

--------------------------------------------------------------------------------
ERROR in app [/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/Flask-0.12.2-py2.7.egg/flask/app.py:1560]:
Exception on /swagger.json [GET]
--------------------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/Flask-0.12.2-py2.7.egg/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/Flask-0.12.2-py2.7.egg/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/api.py", line 313, in wrapper
    resp = resource(*args, **kwargs)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/Flask-0.12.2-py2.7.egg/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/resource.py", line 44, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/api.py", line 771, in get
    return self.api.__schema__
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/Werkzeug-0.12.2-py2.7.egg/werkzeug/utils.py", line 73, in __get__
    value = self.func(obj)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/api.py", line 472, in __schema__
    self._schema = Swagger(self).as_dict()
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/swagger.py", line 168, in as_dict
    paths[extract_path(url)] = self.serialize_resource(ns, resource, url, kwargs)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/swagger.py", line 297, in serialize_resource
    doc = self.extract_resource_doc(resource, url)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/swagger.py", line 234, in extract_resource_doc
    method_params = self.expected_params(method_doc)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/swagger.py", line 248, in expected_params
    parser_params = dict((p['name'], p) for p in expect.__schema__)
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/reqparse.py", line 397, in __schema__
    param = arg.__schema__
  File "/home/marco/dicaprio/venv/local/lib/python2.7/site-packages/flask_restplus/reqparse.py", line 265, in __schema__
    'in': LOCATIONS.get(self.location, 'query')
TypeError: unhashable type: 'list'

Issue is LOCATIONS.get(self.location, 'query') assumes self.location is string .

lamehost commented 6 years ago

Dirty fix:

Replace:

        param = {
            'name': self.name,
            'in': LOCATIONS.get(self.location, 'query')
        }

With:

        location_str = 'query'
        if isinstance(self.location, list):
           location_str = ', '.join(list(set([_ for _ in self.location if _ in LOCATIONS])))
        else:
           location_str = LOCATIONS.get(self.location, 'query')
StudioEtrange commented 6 years ago

Same bug here.

with

operation_arguments6 = api.parser()
operation_arguments6.add_argument('a', required=True,  help='A number', location=['form','args'])
operation_arguments6.add_argument('b', required=True, help='A number', location=['form','args'])

result


    parser_params = dict((p['name'], p) for p in expect.__schema__)
  File "/Users/nomorgan/WORK/stella/workspace/feature_darwin/macos/miniconda/4_2_12_PYTHON3@x64/envs/celery-flask-samples-2/lib/python3.6/site-packages/flask_restplus/reqparse.py", line 397, in __schema__
    param = arg.__schema__
  File "/Users/nomorgan/WORK/stella/workspace/feature_darwin/macos/miniconda/4_2_12_PYTHON3@x64/envs/celery-flask-samples-2/lib/python3.6/site-packages/flask_restplus/reqparse.py", line 265, in __schema__
    'in': LOCATIONS.get(self.location, 'query')
TypeError: unhashable type: 'list'

My requirements.txt

Flask==0.12
flask-restplus==0.10.1
gijswobben commented 6 years ago

Issue still occurs in 0.12.1, although documentation clearly states that this is possible.

winglian commented 4 years ago

@lamehost make location a tuple. see https://github.com/noirbizarre/flask-restplus/blob/4609dc17e8ea04033984aa0f06c4d583ecf16aca/flask_restplus/reqparse.py#L98