Closed danizen closed 7 years ago
I will see if I can do this with security on "Accept", and see if it ends up in the header and converts the response to JSON.
For adding preference on "Accept", "Content-Type" section in header when requesting:
req, resp = app.op['your_operation_id'](**your_parameter')
req.produce('applications/json') # Accept: application/json
req.consume('application/xml') # Content-Type: application/json
A tutorial relative to this part is here
I didn't include xml coder in this project, so if you need to handle xml content-type, you need to install one and write a codec handler by yourself (sample code in tutorial already did it)
I'm not quite sure about your sentence: [...with security on "Accept"], thus if what I provided is not what you want, could you help to describe your scenario more detailedly?
Thanks, I'll try this.
So, I followed part of the mime wiki tutorial, and my XmlCodec doesn't work. However, that's OK, as what I want to do is simply add an Accept header and therefore get JSON instead. When I try
req.produce("application/json")
I get then a backtrace when I try to use it with a pyswagger.contrib.client.requests.Client
object.
Since I'm posting a rather long backtrace, I should also mention that I've got 0.8.27 of pyswagger. Here is the rather long ipython trace:
In [20]: req, resp = app.op['findPetsByStatus'](status=['available'])
In [21]: req2 = req.produce('application/json')
In [22]: id(req2)
Out[22]: 140085523900512
In [23]: id(req)
Out[23]: 140085523900512
In [24]: r = client.request((req,resp,))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-24-0b77ba45e9e3> in <module>()
----> 1 r = client.request((req,resp,))
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/contrib/client/requests.py in request(self, req_and_resp, opt)
72 status=rs.status_code,
73 header=rs.headers,
---> 74 raw=six.BytesIO(rs.content).getvalue()
75 )
76
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/io.py in apply_with(self, status, raw, header)
401 name = schema.name
402 data = self.__op._mime_codec.unmarshal(content_type, self.raw, _type=_type, _format=_format, name=name)
--> 403 self.__data = r.schema._prim_(data, self.__op._prim_factory, ctx=dict(read=True))
404
405 return self
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/spec/v2_0/objects.py in _prim_(self, v, prim_factory, ctx)
90
91 def _prim_(self, v, prim_factory, ctx=None):
---> 92 return prim_factory.produce(self, v, ctx)
93
94
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/__init__.py in produce(self, obj, val, ctx)
180 ret = creater(obj, val, ctx)
181 if _2nd:
--> 182 val = _2nd(obj, ret, val, ctx)
183 ctx['2nd_pass'] = _2nd
184 elif len(obj.properties) or obj.additionalProperties:
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/comm.py in _2nd_pass_obj(obj, ret, val, ctx)
38 #
39 def _2nd_pass_obj(obj, ret, val, ctx):
---> 40 return ret.apply_with(obj, val, ctx)
41
42 def create_obj(obj, v, ctx=None, constructor=None):
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/_array.py in apply_with(self, obj, val, ctx)
35
36 if obj.items and len(val):
---> 37 self.extend(map(functools.partial(ctx['factory'].produce, obj.items), val))
38 val = []
39
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/__init__.py in produce(self, obj, val, ctx)
180 ret = creater(obj, val, ctx)
181 if _2nd:
--> 182 val = _2nd(obj, ret, val, ctx)
183 ctx['2nd_pass'] = _2nd
184 elif len(obj.properties) or obj.additionalProperties:
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/comm.py in _2nd_pass_obj(obj, ret, val, ctx)
38 #
39 def _2nd_pass_obj(obj, ret, val, ctx):
---> 40 return ret.apply_with(obj, val, ctx)
41
42 def create_obj(obj, v, ctx=None, constructor=None):
/home/dan/python-envs/trypyswagger/lib/python3.5/site-packages/pyswagger/primitives/_model.py in apply_with(self, obj, val, ctx)
47 not_found = set(obj.required) - set(six.iterkeys(self))
48 if len(not_found):
---> 49 raise ValueError('requirement not meet: {0}'.format(not_found))
50
51 # remove assigned properties to avoid duplicated
ValueError: requirement not meet: {'name'}
In [25]:
OK - I have some reason to think that this was not your problem, but the sort of assertion I actually want to use pyswagger to test. When I try "findPetsByStatus" with status=['available'] I get the failure on {'name'}. When I try "getPetById", it just works, and similarly for "findPetsByStatus" with status=['sold'].
My conclusion therefore is that the "requirement not met" message is because there is some pet out there without a name, and that name is required in the swagger.yaml So, the response truly was invalid.
Here is it working:
In [36]: req, resp = app.op['getPetById'](petId=3048819905)
In [37]: req.produce('application/json')
Out[37]: <pyswagger.io.Request at 0x7f4ea8dc15f8>
In [38]: r = client.request((req,resp,))
In [39]: r.status
Out[39]: 200
In [40]: r.data
Out[40]:
{'category': {'id': 721582874, 'name': 'dog'},
'id': 3048819905,
'name': 'hello kity',
'photoUrls': ['http://foo.bar.com/1', 'http://foo.bar.com/2'],
'status': 'sold',
'tags': [{'id': 168551466, 'name': 'swagger-codegen-python-pet-tag'}]}
In [41]: req.header
Out[41]: {'Accept': 'application/json'}
FWIW - it is req.produce('application/json')
that sets Accept.
Not sure if I fully understand your intension, but to test findPetsByStatus, you need to provide 'string', not 'list of string'.
# correct
status='available'
# wrong
status=['available']
Thanks for writing pyswagger! Now that I've completed this tiny experiment, https://github.com/danizen/trypyswagger, I can show it to the guy at work who wants to use json-schema.org for validation and show him that this is better for our use case.
It definitely is an array of strings, as the following excerpt of petstore.yaml
shows.
parameters:
- name: "status"
in: "query"
description: "Status values that need to be considered for filter"
required: true
type: "array"
items:
type: "string"
enum:
- "available"
- "pending"
- "sold"
default: "available"
collectionFormat: "multi"
got it, I'm wrong with that part :(
For json-schema validation, you can also refer to this project: https://github.com/Julian/jsonschema, which is highly recommended if you just want to use json-schema
The reason pyswagger didn't use that project to is Swagger (OpenAPI) is not fully compatible with json-schema, so I had to write one by myself.
Thanks for the pointer - both I and the other guy want to stay all Python on the server side, except for a tiny bit of npm/gulp/webpack for managing assets.
@danizen it's actually a project with 1000+ star in python :)
This issue is related to #87 - it would be nice if pyswagger worked out of the box with all of the petstore API. Even a simple get is flumoxed by the lack of either:
My preference would be to be able to add a header such as "Accept" "application/json" in the client. However, I guess I'm not seeing how to do that.