Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[python-fastapi] return 500 if not implemented, added some unittests #19196

Merged
merged 2 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ from fastapi import ( # noqa: F401
Depends,
Form,
Header,
HTTPException,
Path,
Query,
Response,
Expand Down Expand Up @@ -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}}


Expand Down
Original file line number Diff line number Diff line change
@@ -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 changes: 35 additions & 0 deletions modules/openapi-generator/src/test/resources/3_1/nodesc.yaml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Depends,
Form,
Header,
HTTPException,
Path,
Query,
Response,
Expand Down Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Depends,
Form,
Header,
HTTPException,
Path,
Query,
Response,
Expand Down Expand Up @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Depends,
Form,
Header,
HTTPException,
Path,
Query,
Response,
Expand Down Expand Up @@ -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 &lt; 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)


Expand All @@ -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()


Expand All @@ -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 &lt;&#x3D; 5 or &gt; 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)


Expand All @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Depends,
Form,
Header,
HTTPException,
Path,
Query,
Response,
Expand Down Expand Up @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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)


Expand All @@ -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()


Expand All @@ -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