pyopenapi / pyswagger

An OpenAPI (fka Swagger) client & converter in python, which is type-safe, dynamic, spec-compliant.
MIT License
384 stars 88 forks source link

SchemaError: Unsupported collection format 'multi' when converting array: available #87

Closed aaltat closed 7 years ago

aaltat commented 7 years ago

When I have this code:

from pyswagger import App, Security
from pyswagger.contrib.client.requests import Client

app = App._create_('http://petstore.swagger.io/v2/swagger.json')

auth = Security(app)
auth.update_with('api_key', '12312312312312312313q')  # api key
auth.update_with('petstore_auth', '12334546556521123fsfss')  # oauth2

client = Client(auth)
pet_Tom = dict(
    id=123,
    name='Tom',
    photoUrls='https://github.com/',
    status='available')
res = client.request(app.op['addPet'](body=pet_Tom))
print res.status
pet = client.request(app.op['findPetsByStatus'](status='available'))

Then I get this error:

200

  File "C:\tmp\try_swagger.py", line 18, in <module>
    pet = client.request(app.op['findPetsByStatus'](status='available'))
  File "C:\Python27\lib\site-packages\pyswagger\spec\v2_0\objects.py", line 283, in __call__
    _convert_parameter(final(p))
  File "C:\Python27\lib\site-packages\pyswagger\spec\v2_0\objects.py", line 264, in _convert_parameter
    c = p._prim_(v, self._prim_factory, ctx=dict(read=False))
  File "C:\Python27\lib\site-packages\pyswagger\spec\v2_0\objects.py", line 184, in _prim_
    return prim_factory.produce(self.schema, v, ctx) if i == 'body' else prim_factory.produce(self, v, ctx)
  File "C:\Python27\lib\site-packages\pyswagger\primitives\__init__.py", line 182, in produce
    val = _2nd(obj, ret, val, ctx)
  File "C:\Python27\lib\site-packages\pyswagger\primitives\comm.py", line 40, in _2nd_pass_obj
    return ret.apply_with(obj, val, ctx) 
  File "C:\Python27\lib\site-packages\pyswagger\primitives\_array.py", line 32, in apply_with
    raise SchemaError("Unsupported collection format '{0}' when converting array: {1}".format(self.__collection_format, val))
pyswagger.errs.SchemaError: Unsupported collection format 'multi' when converting array: available

Is there a way to workaround the problem?

mission-liao commented 7 years ago

Hi, the type of the parameter is "array", which means you need to provide it as a python list. Like this:

 resp = client.request(app.op['findPetsByStatus'](status=['available', 'sold']))

This case is covered in this test case, so it should work as expected.

aaltat commented 7 years ago

Thank you from the help and pointing me to the right test. When fixing the code to this:

from pyswagger import App, Security
from pyswagger.contrib.client.requests import Client

app = App._create_('http://petstore.swagger.io/v2/swagger.json')

auth = Security(app)
auth.update_with('api_key', '12312312312312312313q')  # api key
auth.update_with('petstore_auth', '12334546556521123fsfss')  # oauth2

client = Client(auth)
pet_Tom = dict(
    id=123,
    name='Tom',
    photoUrls='https://github.com/',
    status='available')
res = client.request(app.op['addPet'](body=pet_Tom))
print res.status
client.request(app.op['findPetsByStatus'](status=['available', 'sold']))

I get a different error:

Traceback (most recent call last):
  File "C:\tmp\try_swagger.py", line 18, in <module>
    client.request(app.op['findPetsByStatus'](status=['available', 'sold']))
  File "C:\Python27\lib\site-packages\pyswagger\contrib\client\requests.py", line 69, in request
    raw=six.BytesIO(rs.content).getvalue()
  File "C:\Python27\lib\site-packages\pyswagger\io.py", line 370, in apply_with
    data = self.__op._mime_codec.unmarshal(content_type, self.raw, _type=_type, _format=_format, name=name)
  File "C:\Python27\lib\site-packages\pyswagger\primitives\codec.py", line 34, in unmarshal
    raise Exception('Could not find codec for %s, data: %s, args: %s' % (mime, data, kwargs))
Exception: Could not find codec for application/xml, data: 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><pets>... NOT PASTING THE LONG XML HERE  ...</status><tags/></Pet></pets>, args: {'_format': None, '_type': u'array', 'name': None}
mission-liao commented 7 years ago

For the XML codec, it's not officially included but could be added (refer to here)

The code snippet I used is:

from pyswagger import App, Security
from pyswagger.contrib.client.requests import Client

# register xml codec
from pyswagger.primitives import MimeCodec
import xmltodict
import dicttoxml

class XmlCodec:
    def marshal(self, value, **kwargs):  # name, _type, _format is available in kwargs
        name = kwargs['name']
        if name:
            return dicttoxml.dicttoxml(value, root=True, custom_root=name, attr_type=False)
        else:
            return '<?xml version="1.0" encoding="UTF-8" ?>' + dicttoxml.dicttoxml(value, root=False, attr_type=False)

    def unmarshal(self, data, **kwargs):  # name, _type, _format is available in kwargs
        return xmltodict.parse(data)

def _create_mime_codec():
    mime_codec = MimeCodec()
    xmlCodec = XmlCodec()
    for _type in ['application', 'text']:
        mime_codec.register('%s/xml' % _type, xmlCodec)
    return mime_codec

_mime_codec = _create_mime_codec()

app = App.load('http://petstore.swagger.io/v2/swagger.json', mime_codec=_mime_codec)
app.prepare(strict=True)

auth = Security(app)
auth.update_with('api_key', '12312312312312312313q')  # api key
auth.update_with('petstore_auth', '12334546556521123fsfss')  # oauth2

client = Client(auth)
pet_Tom = dict(
    id=123,
    name='Tom',
    photoUrls='https://github.com/',
    status='available')
res = client.request(app.op['addPet'](body=pet_Tom))
print res.status
pet = client.request(app.op['findPetsByStatus'](status=['available']))

The error I got is:

not well-formed (invalid token): line 1, column 85938

This error is not related to pyswagger, but related to the broken content returned by petstore.

aaltat commented 7 years ago

Thank you from the help. I am building a PoC solution for our testing purposes and so far this looks promising. I can ignore error for the PoC and let's see how things work after the tool is selected.

I got enough information to proceed and from my point of view, this issue can be closed.

mission-liao commented 7 years ago

Thanks, and please feel free to raise any issue you encounter in the future.