Exemple #1
0
    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
Exemple #2
0
    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'])
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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))
Exemple #6
0
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
Exemple #7
0
    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()
Exemple #8
0
    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