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)
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])
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')
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 + '}')