def _prepare_body(self): """ private function to prepare content for paramType=body """ content_type = self.__consume if not content_type: content_type = self.__op.consumes[ 0] if self.__op.consumes else 'application/json' if self.__op.consumes and content_type not in self.__op.consumes: raise errs.SchemaError( 'content type {0} does not present in {1}'.format( content_type, self.__op.consumes)) # according to spec, payload should be one and only, # so we just return the first value in dict. for parameter in self.__op.parameters: parameter = final(parameter) if getattr(parameter, 'in') == 'body': schema = deref(parameter.schema) _type = schema.type _format = schema.format name = schema.name body = self.__p['body'][parameter.name] return content_type, self.__op._mime_codec.marshal( content_type, body, _type=_type, _format=_format, name=name) return None, None
def _prepare_forms(self): """ private function to prepare content for paramType=form """ content_type = 'application/x-www-form-urlencoded' if self.__op.consumes and content_type not in self.__op.consumes: raise errs.SchemaError('content type {0} does not present in {1}'.format(content_type, self.__op.consumes)) return content_type, six.moves.urllib.parse.urlencode(self.__p['formData'])
def _prepare_body(self): """ private function to prepare content for paramType=body """ content_type = 'application/json' if self.__op.consumes and content_type not in self.__op.consumes: raise errs.SchemaError( 'unable to locate content-type: {0}'.format(content_type)) for v in six.itervalues(self.__p['body']): # according to spec, payload should be one and only, # so we just return the first value in dict. return content_type, json.dumps(v, cls=PrimJSONEncoder) return None, None
def prepare(self, scheme='http', handle_files=True, encoding='utf-8'): """ make this request ready for Clients :param str scheme: scheme used in this request :param bool handle_files: False to skip multipart/form-data encoding :param str encoding: encoding for body content. :rtype: Request """ # combine path parameters into path # TODO: 'dot' is allowed in swagger, but it won't work in python-format self.__path = self.__path.format(**self.__p['path']) # combine path parameters into url self.__url = ''.join([scheme, ':', self.__url.format(**self.__p['path'])]) # header parameters self.__header.update(self.__p['header']) # update data parameter content_type = None if self.__p['file']: if handle_files: content_type, self.__data = self._prepare_files(encoding) else: # client that can encode multipart/form-data, should # access form-data via data property and file from file # property. # only form data can be carried along with files, self.__data = self.__p['formData'] elif self.__p['formData']: content_type, self.__data = self._prepare_forms() elif self.__p['body']: content_type, self.__data = self._prepare_body() else: self.__data = None if content_type: self.__header.update({'Content-Type': content_type}) accept = self.__produce if not accept and self.__op.produces: accept = self.__op.produces[0] if accept: if self.__op.produces and accept not in self.__op.produces: raise errs.SchemaError('accept {0} does not present in {1}'.format(accept, self.__op.produces)) self.__header.update({'Accept': accept}) return self
def __str__(self): """ array primitives should be for 'path', 'header', 'query'. Therefore, this kind of convertion is reasonable. :return: the converted string :rtype: str """ def _conv(p): s = '' for v in self: s = ''.join([s, p if s else '', str(v)]) return s if self.__collection_format == 'csv': return _conv(',') elif self.__collection_format == 'ssv': return _conv(' ') elif self.__collection_format == 'tsv': return _conv('\t') elif self.__collection_format == 'pipes': return _conv('|') else: raise errs.SchemaError('Unsupported collection format when converting to str: {0}'.format(self.__collection_format))
def prim_factory(obj, val, ctx=None): """ factory function to create primitives :param pyswagger.spec.v2_0.objects.Schema obj: spec to construct primitives :param val: value to construct primitives :return: the created primitive """ val = obj.default if val == None else val if val == None: return None cleanup = ctx == None # it's the top-most call in recursive obj = deref(obj) ctx = {} if ctx == None else ctx if 'name' not in ctx and hasattr(obj, 'name'): ctx['name'] = obj.name if 'guard' not in ctx: ctx['guard'] = CycleGuard() if 'addp_schema' not in ctx: ctx['addp_schema'] = None if 'addp' not in ctx: ctx['addp'] = False # cycle guard ctx['guard'].update(obj) ret = None if obj.type: if isinstance(obj.type, six.string_types): if obj.type == 'array': ret = Array() val = ret.apply_with(obj, val, ctx) else: t = prim_obj_map.get((obj.type, obj.format), None) if not t: raise ValueError('Can\'t resolve type from:(' + str(obj.type) + ', ' + str(obj.format) + ')') ret = t(obj, val) else: raise errs.SchemaError('obj.type should be str, not {0}'.format(type(o.type))) elif len(obj.properties) or obj.additionalProperties: ret = Model(obj) val = ret.apply_with(obj, val, ctx) if isinstance(ret, (Date, Datetime, Byte, File)): # it's meanless to handle allOf for these types. return ret is_member = hasattr(ret, 'apply_with') def _apply(r, o, v, c): if is_member == True: v = r.apply_with(o, v, c) else: apply_with(r, o) return v # handle allOf for Schema Object allOf = getattr(obj, 'allOf', None) if allOf: not_applied = [] for a in allOf: a = deref(a) if not ret: # try to find right type for this primitive. ret = prim_factory(a, val, ctx) is_member = hasattr(ret, 'apply_with') else: val = _apply(ret, a, val, ctx) if not ret: # if we still can't determine the type, # keep this Schema object for later use. not_applied.append(a) if ret: for a in not_applied: val = _apply(ret, a, val, ctx) if ret and cleanup and hasattr(ret, 'cleanup'): val = ret.cleanup(val, ctx) return ret
def _prepare_files(self, encoding): """ private function to prepare content for paramType=form with File """ content_type = 'multipart/form-data' if self.__op.consumes and content_type not in self.__op.consumes: raise errs.SchemaError( 'unable to locate content-type: {0}'.format(content_type)) boundary = uuid4().hex content_type += '; boundary={0}' content_type = content_type.format(boundary) # init stream body = io.BytesIO() w = codecs.getwriter(encoding) for k, v in self.__p['formData']: body.write(six.b('--{0}\r\n'.format(boundary))) w(body).write( 'Content-Disposition: form-data; name="{0}"'.format(k)) body.write(six.b('\r\n')) body.write(six.b('\r\n')) w(body).write(v) body.write(six.b('\r\n')) # begin of file section for k, v in six.iteritems(self.__p['file']): body.write(six.b('--{0}\r\n'.format(boundary))) # header w(body).write( 'Content-Disposition: form-data; name="{0}"; filename="{1}"'. format(k, v.filename)) body.write(six.b('\r\n')) if 'Content-Type' in v.header: w(body).write('Content-Type: {0}'.format( v.header['Content-Type'])) body.write(six.b('\r\n')) if 'Content-Transfer-Encoding' in v.header: w(body).write('Content-Transfer-Encoding: {0}'.format( v.header['Content-Transfer-Encoding'])) body.write(six.b('\r\n')) body.write(six.b('\r\n')) # body if not v.data: with open(v.filename, 'rb') as f: body.write(f.read()) else: data = v.data.read() if isinstance(data, six.text_type): w(body).write(data) else: body.write(data) body.write(six.b('\r\n')) # final boundary body.write(six.b('--{0}--\r\n'.format(boundary))) return content_type, body.getvalue()
def prepare(self, scheme='http', handle_files=True, encoding='utf-8'): """ make this request ready for Clients :param str scheme: scheme used in this request :param bool handle_files: False to skip multipart/form-data encoding :param str encoding: encoding for body content. :rtype: Request """ if isinstance(scheme, list): if self.__scheme is None: scheme = scheme.pop() else: if self.__scheme in scheme: scheme = self.__scheme else: raise Exception( 'preferred scheme:{} is not supported by the client or spec:{}' .format(self.__scheme, scheme)) elif not isinstance(scheme, six.string_types): raise ValueError('"scheme" should be a list or string') # combine path parameters into path # TODO: 'dot' is allowed in swagger, but it won't work in python-format path_params = {} for k, v in six.iteritems(self.__p['path']): path_params[k] = six.moves.urllib.parse.quote_plus(v) self.__path = self.__path.format(**path_params) # combine path parameters into url self.__url = ''.join([scheme, ':', self.__url.format(**path_params)]) # header parameters self.__header.update(self.__p['header']) # update data parameter content_type = None if self.__p['file']: if handle_files: content_type, self.__data = self._prepare_files(encoding) else: # client that can encode multipart/form-data, should # access form-data via data property and file from file # property. # only form data can be carried along with files, self.__data = self.__p['formData'] elif self.__p['formData']: content_type, self.__data = self._prepare_forms() elif self.__p['body']: content_type, self.__data = self._prepare_body() else: self.__data = None if content_type: self.__header.update({'Content-Type': content_type}) accept = self.__produce if not accept and self.__op.produces: accept = self.__op.produces[0] if accept: if self.__op.produces and accept not in self.__op.produces: raise errs.SchemaError( 'accept {0} does not present in {1}'.format( accept, self.__op.produces)) self.__header.update({'Accept': accept}) return self