Beispiel #1
0
def _endpoint_to_route_path(endpoint: swagger_to.intermediate.Endpoint) -> str:
    """
    Convert an endpoint path to Gorrila Mux route path.

    :param endpoint: whose path we need to convert
    :return: Gorrila Mux route path
    """
    token_pth = swagger_to.tokenize_path(path=endpoint.path)

    tkns = token_pth.tokens[:]

    for param in endpoint.parameters:
        if param.in_what != 'path':
            continue

        if param.name not in token_pth.parameter_to_token_indices:
            continue

        if not isinstance(param.typedef, swagger_to.intermediate.Primitivedef):
            raise ValueError(
                "Expected path parameter {!r} in the path {!r} to be primitive, but got: {!r}"
                .format(param.name, endpoint.path, type(param.typedef)))

        assert isinstance(param.typedef, swagger_to.intermediate.Primitivedef)
        if param.typedef.pattern != '':
            param_in_route = '{' + param.name + ":" + param.typedef.pattern + "}"
        else:
            param_in_route = '{' + param.name + '}'

        for i in token_pth.parameter_to_token_indices[param.name]:
            tkns[i] = param_in_route

    return "".join(tkns)
Beispiel #2
0
    def test_path_tokenization(self):
        pth = "/{hello}/from-me/hello/{hello}/{wicked / one}/some more?q=1#a{unclosed&}"

        token_pth = swagger_to.tokenize_path(path=pth)

        self.assertEqual("".join(token_pth.tokens), pth)
        self.assertListEqual(token_pth.parameter_to_token_indices["hello"], [1, 3])
Beispiel #3
0
def _write_request(request: Request, fid: TextIO) -> None:
    """
    Generate the code of the request function.

    :param request: function definition
    :param fid: target
    :return:
    """
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-statements
    # pylint: disable=too-many-branches
    description = 'Contains a "{}" request to the endpoint: `{}`, to be sent with Http.send'.format(
        request.method, request.path)
    if request.description:
        description += '\n\n' + request.description
    _write_top_level_description(description=description, fid=fid)
    fid.write('\n')

    types = []  # type List[str]
    names = []  # type List[str]
    for param in request.parameters:
        if param.typedef is None:
            raise ValueError(
                "Unexpected None typedef of param {!r} in request {!r}".format(
                    param.name, request.operation_id))

        if param.required:
            types.append(_type_expression(typedef=param.typedef))
            names.append(swagger_to.camel_case(identifier=param.name))
        else:
            types.append('Maybe {}'.format(
                _type_expression(typedef=param.typedef)))
            names.append('maybe{}'.format(
                swagger_to.capital_camel_case(param.name)))

    return_type = None  # type: Optional[str]
    return_type_decoder = None  # type: Optional[str]
    if '200' in request.responses:
        resp = request.responses['200']
        if resp.typedef is not None:
            return_type = _argument_expression(typedef=resp.typedef)
            return_type_decoder = _argument_decoder_expression(
                typedef=resp.typedef)

    # function signature and arguments
    function_name = '{}Request'.format(
        _request_function_name(request.operation_id))
    types = ["String", "Maybe Time.Time", "Bool"] + types
    names = ["prefix", "maybeTimeout", "withCredentials"] + names
    types_str = ' -> '.join(types)
    types_str += ' -> '
    names_str = ' '.join(names)

    line1 = function_name + ' : ' + types_str
    if return_type is None:
        line1 += 'Http.Request String\n'
    else:
        line1 += 'Http.Request {}\n'.format(return_type)
    line2 = function_name + ' ' + names_str + ' ='
    indent = 1

    if len(line1) <= 120:
        fid.write(line1)
        fid.write(line2)
    else:
        fid.write(function_name + ' :\n')
        join_str = '\n' + INDENT + '-> '

        fid.write(INDENT + '{}\n'.format(join_str.join(types)))
        if return_type is None:
            fid.write(INDENT + '-> Http.Request String\n')
        else:
            fid.write(INDENT + '-> Http.Request {}\n'.format(return_type))

        if len(line2) > 120:
            fid.write(function_name)
            join_str = '\n' + INDENT
            fid.write('\n' + INDENT + '{}'.format(join_str.join(names)))

            fid.write(' =')
            indent = 2
        else:
            fid.write(line2)
    fid.write('\n')

    name_to_parameters = {param.name: param for param in request.parameters}

    rel_path = request.path[1:] if request.path.startswith(
        '/') else request.path

    fid.write(INDENT * indent + 'let\n')

    # path parameters
    token_pth = swagger_to.tokenize_path(path=rel_path)
    url_name = 'baseUrl' if request.query_parameters else 'url'
    if not token_pth.parameter_to_token_indices:
        fid.write(INDENT * (indent + 1) +
                  '{} = prefix ++ "{}"\n'.format(url_name, rel_path))
    else:
        fid.write(INDENT * (indent + 1) + '{} = prefix'.format(url_name))
        for i, tkn in enumerate(token_pth.tokens):
            fid.write("\n")

            if i in token_pth.token_index_to_parameter:
                param_name = token_pth.token_index_to_parameter[i]
                param = name_to_parameters[param_name]
                camel_case_name = swagger_to.camel_case(identifier=param.name)
                if not isinstance(param.typedef, Stringdef):
                    camel_case_name = '(toString {})'.format(camel_case_name)

                fid.write(INDENT * (indent + 2) +
                          '++ {}'.format(camel_case_name))
            else:
                # escape special characters
                fid.write(INDENT * (indent + 2) +
                          '++ "{}"'.format(_escape_string(text=tkn)))

    if request.path_parameters and request.query_parameters:
        fid.write("\n")

    # query parameters
    if request.query_parameters:
        required = []  # type: List[str]
        not_required = []  # type: List[str]

        for i, param in enumerate(request.query_parameters):
            if param.required:
                arg_name = swagger_to.camel_case(identifier=param.name)
                arg = arg_name
                if not isinstance(param.typedef, Stringdef):
                    arg = '(toString {})'.format(arg_name)

                required.append('("' + param.name + '", ' + arg + ')')
            else:
                arg_name = 'maybe{}'.format(
                    swagger_to.capital_camel_case(identifier=param.name))
                arg = arg_name
                if not isinstance(param.typedef, Stringdef):
                    arg = '(Maybe.map toString {})'.format(arg_name)

                not_required.append('("' + param.name + '", ' + arg + ')')

        fid.write(INDENT * (indent + 1) + 'queryString = \n')
        fid.write(INDENT * (indent + 2) + 'paramsToQuery\n')

        if required:
            fid.write((INDENT * (indent + 3)) + "[ ")
            for i, tuple_str in enumerate(required):
                if i == 0:
                    fid.write(tuple_str + "\n")
                else:
                    fid.write((INDENT * (indent + 3)) + ", " + tuple_str +
                              "\n")
            fid.write((INDENT * (indent + 3)) + "]\n")
        else:
            fid.write((INDENT * (indent + 3)) + '[]\n')

        if not_required:
            fid.write((INDENT * (indent + 3)) + "[ ")
            for i, tuple_str in enumerate(not_required):
                if i == 0:
                    fid.write(tuple_str + "\n")
                else:
                    fid.write((INDENT * (indent + 3)) + ", " + tuple_str +
                              "\n")
            fid.write((INDENT * (indent + 3)) + "]\n")
        else:
            fid.write((INDENT * (indent + 3)) + '[]\n')

        fid.write(INDENT * (indent + 1) + 'url = baseUrl ++ queryString\n')

    fid.write(indent * INDENT + 'in\n')

    mth = request.method.upper()

    fid.write(INDENT * indent + 'Http.request\n')
    fid.write(INDENT * (indent + 1) + '{ body = ')
    if request.body_parameter is not None:
        if request.body_parameter.typedef is None:
            raise ValueError(
                "Unexpected None typedef of body_parameter in request {!r}".
                format(request.operation_id))

        if not request.body_parameter.required:
            fid.write('Json.Encode.Extra.maybe ({}'.format(
                _type_encoder(request.body_parameter.typedef)))
        fid.write('({}'.format(_type_encoder(request.body_parameter.typedef)))

        fid.write(' {}) |> Http.jsonBody'.format(
            swagger_to.camel_case(identifier=request.body_parameter.name)))
    else:
        fid.write('Http.emptyBody')
    fid.write('\n')
    if return_type is None:
        fid.write(INDENT * (indent + 1) + ', expect = Http.expectString\n')
    else:
        fid.write(
            INDENT * (indent + 1) +
            ', expect = Http.expectJson {}\n'.format(return_type_decoder))
    fid.write(INDENT * (indent + 1) + ', headers = []\n')
    fid.write(INDENT * (indent + 1) + ', method = "{}"\n'.format(mth))
    fid.write(INDENT * (indent + 1) + ', timeout = maybeTimeout\n')
    fid.write(INDENT * (indent + 1) + ', url = url\n')
    fid.write(INDENT * (indent + 1) + ', withCredentials = withCredentials\n')
    fid.write(INDENT * (indent + 1) + '}\n')
Beispiel #4
0
def _write_request(request: Request, fid: TextIO) -> None:
    """
    Generate the code of the request function.

    :param request: function definition
    :param fid: target
    :return:
    """
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-statements
    # pylint: disable=too-many-branches
    description = 'Sends a request to the endpoint: {} {}'.format(
        request.path, request.method)
    if request.description:
        description += '\n\n' + request.description
    _write_description(description, INDENT, fid)
    fid.write('\n')

    prefix = INDENT + 'public {}('.format(request.operation_id)

    args = []  # type: List[str]
    for param in request.parameters:
        if param.typedef is None:
            raise ValueError(
                'Unexpected None typedef in param {!r} of request {!r}'.format(
                    param.name, request.operation_id))

        args.append('{}{}: {}'.format(param.name,
                                      '?' if not param.required else '',
                                      _type_expression(typedef=param.typedef)))

    return_type = ''
    if '200' in request.responses:
        resp = request.responses['200']
        if resp.typedef is not None:
            return_type = _type_expression(typedef=resp.typedef)

    if not return_type:
        return_type = 'any'

    suffix = '): Observable<{} | HttpErrorResponse> {{'.format(return_type)

    line = prefix + ', '.join(args) + suffix
    if len(line) <= 120:
        fid.write(line)
    else:
        fid.write(prefix)
        fid.write('\n')

        for i, arg in enumerate(args):
            fid.write(3 * INDENT + arg)

            if i < len(args) - 1:
                fid.write(',\n')

        fid.write(suffix)
    fid.write('\n')

    name_to_parameters = {param.name: param for param in request.parameters}

    rel_path = request.path[1:] if request.path.startswith(
        '/') else request.path

    # path parameters
    token_pth = swagger_to.tokenize_path(path=rel_path)

    if not token_pth.parameter_to_token_indices and not request.query_parameters:
        fid.write(INDENT * 2 +
                  'const url = this.url_prefix + "{}";\n'.format(rel_path))
    else:
        if not token_pth.parameter_to_token_indices:
            fid.write(INDENT * 2 +
                      'let url = this.url_prefix + "{}";'.format(rel_path))
        else:
            fid.write(INDENT * 2 + 'let url = this.url_prefix;')
            for i, tkn in enumerate(token_pth.tokens):
                fid.write("\n")

                if i in token_pth.token_index_to_parameter:
                    param_name = token_pth.token_index_to_parameter[i]
                    param = name_to_parameters[param_name]

                    if param.typedef is None:
                        raise ValueError(
                            'Unexpected None typedef in param {!r} and request {!r}'
                            .format(param.name, request.operation_id))

                    fid.write(INDENT * 2 +
                              'url += encodeURIComponent({});'.format(
                                  _to_string_expression(typedef=param.typedef,
                                                        variable=param.name)))
                else:
                    fid.write(
                        INDENT * 2 + 'url += encodeURIComponent("{}");'.format(
                            tkn.replace('\\', '\\\\').replace('\n', '\\n').
                            replace('\r', '\\r').replace('\t', '\\t')))

    if request.path_parameters and request.query_parameters:
        fid.write("\n")

    # query parameters
    if request.query_parameters:
        fid.write('\n')
        fid.write(INDENT * 2 + 'url += "?";\n')

        for i, param in enumerate(request.query_parameters):
            amp = ''  # used to concatenate query parameters
            if i > 0:
                fid.write("\n\n")
                amp = '&'

            if param.typedef is None:
                raise ValueError(
                    'Unexpected None typedef in param {!r} and request {!r}'.
                    format(param.name, request.operation_id))

            if param.required:
                fid.write(INDENT * 2 +
                          'url += "{}{}=" + encodeURIComponent({});'.format(
                              amp, param.name,
                              _to_string_expression(typedef=param.typedef,
                                                    variable=param.name)))
            else:
                fid.write(INDENT * 2 + 'if ({}) {{\n'.format(param.name))
                fid.write(INDENT * 3 +
                          'url += "{}{}=" + encodeURIComponent({});\n'.format(
                              amp, param.name,
                              _to_string_expression(typedef=param.typedef,
                                                    variable=param.name)))
                fid.write(INDENT * 2 + '}')

        fid.write('\n')

    fid.write('\n')

    mth = request.method.lower()
    if request.body_parameter is not None:
        if request.body_parameter.required:
            fid.write(INDENT * 2 +
                      'let observable = this.http.request(url, \n')
            fid.write(
                INDENT * 3 +
                'new RequestOptions({{method: "{0}", body: JSON.stringify({1})}}));\n'
                .format(mth, request.body_parameter.name))
        else:
            fid.write(INDENT * 2 + 'let observable: Observable<any>;\n')
            fid.write(INDENT * 2 +
                      'if ({}) {{\n'.format(request.body_parameter.name))
            fid.write(INDENT * 3 + 'this.http.request(url, \n')
            fid.write(
                INDENT * 4 +
                'new RequestOptions({{method: "{0}", body: JSON.stringify({1})}}));\n'
                .format(mth, request.body_parameter.name))
            fid.write(INDENT * 2 + '} else {\n')
            fid.write(INDENT * 3 + 'observable = this.http.request(url, '
                      'new RequestOptions({{method: "{0}"}}));\n'.format(mth))
            fid.write(INDENT * 2 + '}\n')
    else:
        fid.write(INDENT * 2 +
                  'let observable = this.http.{}(url);\n'.format(mth))

    return_var = 'observable'
    if return_type != 'any':
        fid.write(
            INDENT * 2 +
            'let typed_observable = observable.map(res => (res.json() as {}));\n'
            .format(return_type))
        return_var = 'typed_observable'

    fid.write(INDENT * 2 + 'if (this.on_error) {\n')
    fid.write(
        INDENT * 3 +
        'return {0}.catch(err => this.on_error(err))\n'.format(return_var))
    fid.write(INDENT * 2 + '}\n')
    fid.write(INDENT * 2 + 'return {};\n'.format(return_var))

    fid.write(INDENT + '}')