forked from loafle/openapi-generator-original
[python-fastapi] return 500 if not implemented, added some unittests (#19196)
* [python-fastapi] Added some tests for FastAPI generator 1. Checks the generation of the implementation package. 2. Checks if the endpoints with and without descriptions generate correct output. Signed-off-by: Nikita Vakula <programmistov.programmist@gmail.com> * [python-fastapi] Raise 500 if there is no implementation Signed-off-by: Nikita Vakula <programmistov.programmist@gmail.com> --------- Signed-off-by: Nikita Vakula <programmistov.programmist@gmail.com>
This commit is contained in:
parent
f44bc30d20
commit
e542b06869
@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
|
||||
Depends,
|
||||
Form,
|
||||
Header,
|
||||
HTTPException,
|
||||
Path,
|
||||
Query,
|
||||
Response,
|
||||
@ -65,7 +66,9 @@ async def {{operationId}}(
|
||||
{{/hasAuthMethods}}
|
||||
) -> {{returnType}}{{^returnType}}None{{/returnType}}:
|
||||
{{#notes}}"""{{.}}"""
|
||||
{{/notes}}return await Base{{classname}}.subclasses[0]().{{operationId}}({{#allParams}}{{>impl_argument}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
{{/notes}}if not Base{{classname}}.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await Base{{classname}}.subclasses[0]().{{operationId}}({{#allParams}}{{>impl_argument}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
{{^-last}}
|
||||
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
package org.openapitools.codegen.python;
|
||||
|
||||
import org.openapitools.codegen.DefaultGenerator;
|
||||
import org.openapitools.codegen.TestUtils;
|
||||
import org.openapitools.codegen.config.CodegenConfigurator;
|
||||
import org.testng.annotations.Test;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
public class PythonFastapiCodegenTest {
|
||||
@Test
|
||||
public void testAdditionalPropertiesPutForConfigValues() throws Exception {
|
||||
File output = Files.createTempDirectory("test").toFile();
|
||||
output.deleteOnExit();
|
||||
|
||||
final String IMPL_PKG = "impl_package";
|
||||
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||
.setGeneratorName("python-fastapi")
|
||||
.setPackageName("nodesc")
|
||||
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
|
||||
.setInputSpec("src/test/resources/3_1/nodesc.yaml")
|
||||
.addAdditionalProperty(CodegenConstants.FASTAPI_IMPLEMENTATION_PACKAGE, IMPL_PKG);
|
||||
|
||||
DefaultGenerator generator = new DefaultGenerator();
|
||||
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
|
||||
files.forEach(File::deleteOnExit);
|
||||
|
||||
TestUtils.assertFileExists(Paths.get(output.getAbsolutePath(), "/src", IMPL_PKG, "__init__.py"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndpointSpecsWithoutDescription() throws IOException {
|
||||
File output = Files.createTempDirectory("test").toFile();
|
||||
output.deleteOnExit();
|
||||
|
||||
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||
.setGeneratorName("python-fastapi")
|
||||
.setPackageName("nodesc")
|
||||
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
|
||||
.setInputSpec("src/test/resources/3_1/nodesc.yaml");
|
||||
|
||||
DefaultGenerator generator = new DefaultGenerator();
|
||||
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
|
||||
files.forEach(File::deleteOnExit);
|
||||
|
||||
TestUtils.assertFileContains(Paths.get(output + "/src/nodesc/apis/nodesc_api.py"),
|
||||
"return await BaseNodescApi.subclasses[0]().nodesc()\n");
|
||||
TestUtils.assertFileContains(Paths.get(output + "/src/nodesc/apis/desc_api.py"),
|
||||
"return await BaseDescApi.subclasses[0]().desc()\n");
|
||||
}
|
||||
}
|
35
modules/openapi-generator/src/test/resources/3_1/nodesc.yaml
Normal file
35
modules/openapi-generator/src/test/resources/3_1/nodesc.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
description: >-
|
||||
Yet another example.
|
||||
version: 1.0.0
|
||||
title: OpenAPI example
|
||||
tags:
|
||||
- name: nodesc
|
||||
description: Endpoints have no description
|
||||
- name: desc
|
||||
description: Endpoints have description
|
||||
paths:
|
||||
/nodesc:
|
||||
post:
|
||||
tags:
|
||||
- nodesc
|
||||
summary: dummy operation
|
||||
operationId: nodesc
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
'405':
|
||||
description: Invalid input
|
||||
/desc:
|
||||
post:
|
||||
tags:
|
||||
- desc
|
||||
summary: dummy operation
|
||||
description: 'Description'
|
||||
operationId: desc
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
'405':
|
||||
description: Invalid input
|
@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
|
||||
Depends,
|
||||
Form,
|
||||
Header,
|
||||
HTTPException,
|
||||
Path,
|
||||
Query,
|
||||
Response,
|
||||
@ -46,4 +47,6 @@ async def fake_query_param_default(
|
||||
no_default: str = Query(None, description="no default value", alias="noDefault"),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BaseFakeApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseFakeApi.subclasses[0]().fake_query_param_default(has_default, no_default)
|
||||
|
@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
|
||||
Depends,
|
||||
Form,
|
||||
Header,
|
||||
HTTPException,
|
||||
Path,
|
||||
Query,
|
||||
Response,
|
||||
@ -50,6 +51,8 @@ async def add_pet(
|
||||
),
|
||||
) -> Pet:
|
||||
""""""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().add_pet(pet)
|
||||
|
||||
|
||||
@ -70,6 +73,8 @@ async def delete_pet(
|
||||
),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().delete_pet(petId, api_key)
|
||||
|
||||
|
||||
@ -90,6 +95,8 @@ async def find_pets_by_status(
|
||||
),
|
||||
) -> List[Pet]:
|
||||
"""Multiple status values can be provided with comma separated strings"""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().find_pets_by_status(status)
|
||||
|
||||
|
||||
@ -110,6 +117,8 @@ async def find_pets_by_tags(
|
||||
),
|
||||
) -> List[Pet]:
|
||||
"""Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing."""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().find_pets_by_tags(tags)
|
||||
|
||||
|
||||
@ -131,6 +140,8 @@ async def get_pet_by_id(
|
||||
),
|
||||
) -> Pet:
|
||||
"""Returns a single pet"""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().get_pet_by_id(petId)
|
||||
|
||||
|
||||
@ -153,6 +164,8 @@ async def update_pet(
|
||||
),
|
||||
) -> Pet:
|
||||
""""""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().update_pet(pet)
|
||||
|
||||
|
||||
@ -174,6 +187,8 @@ async def update_pet_with_form(
|
||||
),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().update_pet_with_form(petId, name, status)
|
||||
|
||||
|
||||
@ -195,4 +210,6 @@ async def upload_file(
|
||||
),
|
||||
) -> ApiResponse:
|
||||
""""""
|
||||
if not BasePetApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BasePetApi.subclasses[0]().upload_file(petId, additional_metadata, file)
|
||||
|
@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
|
||||
Depends,
|
||||
Form,
|
||||
Header,
|
||||
HTTPException,
|
||||
Path,
|
||||
Query,
|
||||
Response,
|
||||
@ -46,6 +47,8 @@ async def delete_order(
|
||||
orderId: str = Path(..., description="ID of the order that needs to be deleted"),
|
||||
) -> None:
|
||||
"""For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors"""
|
||||
if not BaseStoreApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseStoreApi.subclasses[0]().delete_order(orderId)
|
||||
|
||||
|
||||
@ -64,6 +67,8 @@ async def get_inventory(
|
||||
),
|
||||
) -> Dict[str, int]:
|
||||
"""Returns a map of status codes to quantities"""
|
||||
if not BaseStoreApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseStoreApi.subclasses[0]().get_inventory()
|
||||
|
||||
|
||||
@ -82,6 +87,8 @@ async def get_order_by_id(
|
||||
orderId: int = Path(..., description="ID of pet that needs to be fetched", ge=1, le=5),
|
||||
) -> Order:
|
||||
"""For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions"""
|
||||
if not BaseStoreApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseStoreApi.subclasses[0]().get_order_by_id(orderId)
|
||||
|
||||
|
||||
@ -99,4 +106,6 @@ async def place_order(
|
||||
order: Order = Body(None, description="order placed for purchasing the pet"),
|
||||
) -> Order:
|
||||
""""""
|
||||
if not BaseStoreApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseStoreApi.subclasses[0]().place_order(order)
|
||||
|
@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
|
||||
Depends,
|
||||
Form,
|
||||
Header,
|
||||
HTTPException,
|
||||
Path,
|
||||
Query,
|
||||
Response,
|
||||
@ -48,6 +49,8 @@ async def create_user(
|
||||
),
|
||||
) -> None:
|
||||
"""This can only be done by the logged in user."""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().create_user(user)
|
||||
|
||||
|
||||
@ -67,6 +70,8 @@ async def create_users_with_array_input(
|
||||
),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().create_users_with_array_input(user)
|
||||
|
||||
|
||||
@ -86,6 +91,8 @@ async def create_users_with_list_input(
|
||||
),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().create_users_with_list_input(user)
|
||||
|
||||
|
||||
@ -106,6 +113,8 @@ async def delete_user(
|
||||
),
|
||||
) -> None:
|
||||
"""This can only be done by the logged in user."""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().delete_user(username)
|
||||
|
||||
|
||||
@ -124,6 +133,8 @@ async def get_user_by_name(
|
||||
username: str = Path(..., description="The name that needs to be fetched. Use user1 for testing."),
|
||||
) -> User:
|
||||
""""""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().get_user_by_name(username)
|
||||
|
||||
|
||||
@ -142,6 +153,8 @@ async def login_user(
|
||||
password: str = Query(None, description="The password for login in clear text", alias="password"),
|
||||
) -> str:
|
||||
""""""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().login_user(username, password)
|
||||
|
||||
|
||||
@ -160,6 +173,8 @@ async def logout_user(
|
||||
),
|
||||
) -> None:
|
||||
""""""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().logout_user()
|
||||
|
||||
|
||||
@ -181,4 +196,6 @@ async def update_user(
|
||||
),
|
||||
) -> None:
|
||||
"""This can only be done by the logged in user."""
|
||||
if not BaseUserApi.subclasses:
|
||||
raise HTTPException(status_code=500, detail="Not implemented")
|
||||
return await BaseUserApi.subclasses[0]().update_user(username, user)
|
||||
|
Loading…
x
Reference in New Issue
Block a user