Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using a list for "Multiple Locations" yields an unexpected exception #725

Open
odi79 opened this issue Oct 4, 2019 · 2 comments
Open

Using a list for "Multiple Locations" yields an unexpected exception #725

odi79 opened this issue Oct 4, 2019 · 2 comments
Labels

Comments

@odi79
Copy link

odi79 commented Oct 4, 2019

According to section "Multiple Locations" in the documentation (https://flask-restplus.readthedocs.io/en/stable/parsing.html) the following holds:

"Multiple argument locations can be specified by passing a list to location:
parser.add_argument('text', location=['headers', 'values'])
When multiple locations are specified, the arguments from all locations specified are combined into a single MultiDict. The last location listed takes precedence in the result set."

However, trying to use a list for the location parameter yields an exception when the "schema" method is executed.

Example:

myargs = reqparse.RequestParser()
myargs.add_argument('label', type=str, required=True, help='Test', location=['values', 'json'])
...
@ns.expect(myargs)
...

Expected behavior:

Due to the last location "json", the Swagger file should show 'in "body"' for that argument.

Actual behavior:

Exception occuring since a list is unexpected.

2019-10-04 17:44:51,729 ERROR api: Unable to render schema
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/api.py", line 483, in __schema__
    self._schema = Swagger(self).as_dict()
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/swagger.py", line 177, in as_dict
    paths[extract_path(url)] = self.serialize_resource(ns, resource, url, kwargs)
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/swagger.py", line 336, in serialize_resource
    doc = self.extract_resource_doc(resource, url)
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/swagger.py", line 255, in extract_resource_doc
    method_params = self.expected_params(method_doc)
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/swagger.py", line 291, in expected_params
    parser_params = OrderedDict((p['name'], p) for p in expect.__schema__)
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/reqparse.py", line 405, in __schema__
    param = arg.__schema__
  File "/usr/local/lib/python3.5/dist-packages/flask_restplus/reqparse.py", line 269, in __schema__
    'in': LOCATIONS.get(self.location, 'query')
TypeError: unhashable type: 'list'

Resolution:

Current lines 265ff in reqparse.py:

    @property 
    def __schema__(self):`
        if self.location == 'cookie':
            return
        param = {
            'name': self.name,
            'in': LOCATIONS.get(self.location, 'query')
        }

New lines 265ff in reqparse.py:

    @property
    def __schema__(self):
        if self.location == 'cookie':
            return
        if isinstance(self.location, six.string_types):
            location = self.location
        else:
            location = self.location[-1] # last location listed takes precedence in the result set, thus use this here
        param = {
            'name': self.name,
            'in': LOCATIONS.get(location, 'query')           
        }
@odi79
Copy link
Author

odi79 commented Oct 4, 2019

And here's the diff for "reqparse.py" for the resolution stated above:

265a266,269
>         if isinstance(self.location, six.string_types):
>             location = self.location
>         else:
>             location = self.location[-1]
268c272
<             'in': LOCATIONS.get(self.location, 'query')
---
>             'in': LOCATIONS.get(location, 'query')

@SteadBytes
Copy link
Collaborator

SteadBytes commented Oct 10, 2019

Well spotted! This looks fine to me, could you please create a PR with your proposed change in it including some more extensive for this in

def test_location_header_list(self):
?

@SteadBytes SteadBytes added the bug label Oct 10, 2019
odi79 pushed a commit to odi79/flask-restplus that referenced this issue Oct 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants